home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc / Sample Code / Sample Editors⁄Viewers / Cappuccino / Source / Cappuccino.cpp < prev    next >
Encoding:
Text File  |  1995-12-11  |  131.4 KB  |  4,141 lines  |  [TEXT/MPS ]

  1. /*------------------------------------------------------------------------------
  2.  
  3.     File:            Cappuccino.cpp
  4.     
  5.     Written by:        Steve Smith & Troy Gaul
  6.     
  7.     Copyright:        © 1995 by Apple Computer, Inc., all rights reserved.
  8.     
  9.     Description:    Cappuccino demonstrates the most basic functions and
  10.                     responsibilities of an OpenDoc™ leaf part.
  11.     
  12.     
  13.     Demonstrates:    The following recipes were used in implementing
  14.                     Cappuccino:
  15.                      1. Open
  16.                      2. Adding A Display Frame
  17.                      3. Adding A Facet
  18.                      4. Part Drawing
  19.                      5. Refcounting Geometry
  20.                      6. ViewTypes & Presentations
  21.                      7. Display Frame 'ternalization
  22.                      8. Part Init & Externalization
  23.                      9. Part Init & partWrapper
  24.                     10. Part Storage Model
  25.                     11. Persistent Reference
  26.                     12. RefCounting
  27.                     13. Storage Unit
  28.                     14. Activation
  29.                     15. Basic Event Handling
  30.                     16. Menus
  31.                     17. Windows & Dialogs
  32.                     18. Exception Handling
  33.                     19. Memory Manager
  34.                     20. Using Resources
  35.                     21. Lazy Frame Internalization
  36.                     22. Multiple Kind Support
  37.                     
  38.                     Also, recipes for the following features are implemented:
  39.                     
  40.                         Scripting
  41.                         Undo
  42.                         Promises
  43.                         Printing
  44.                         Clipboard support
  45.                         Drag and drop
  46.                         Settings extension
  47.                         Translation
  48.     
  49.     
  50.     Notes:            • For methods where it is necessary to call the parent class
  51.                     implementation, the calls are made from the SOM class. See
  52.                     som_Cappuccino.cpp and the Class Reference to know whether
  53.                     you need to call the parent class from any method.                    
  54.     
  55. ------------------------------------------------------------------------------*/
  56.  
  57. // -- Compiler/Preprocessor Switches --
  58.  
  59. #ifndef _COMPILERDEFS_
  60. #include "CompDefs.h"
  61. #endif
  62.  
  63. // -- OpenDoc Utilities --
  64.  
  65. #ifndef _EXCEPT_
  66. // Exceptions define several important macros (eg. CHECKENV)
  67. // which are used in the SOM method dispatch glue. If Except.h
  68. // is not included early enough, exceptions may not be thrown
  69. // correctly when returning from a SOM method with the "ev" parameter set.
  70. #include <Except.h>
  71. #endif
  72.  
  73. // -- Cappuccino Includes --
  74.  
  75. #ifndef _CAPPUCCINO_
  76. #include "Cappuccino.h"
  77. #endif
  78.  
  79. #ifndef _CAPPUCCINOACTION_
  80. #include "CappuccinoAction.h"
  81. #endif
  82.  
  83. #ifndef _CAPPUCCINOCONTENT_
  84. #include "CappuccinoContent.h"
  85. #endif
  86.  
  87. #ifndef _CAPPUCCINODEF_
  88. #include "CappuccinoDef.h"
  89. #endif
  90.  
  91. #ifndef _CAPPUCCINOGLOBALS_
  92. #include "CappuccinoGlobals.h"
  93. #endif
  94.  
  95. #ifndef _CAPPUCCINOPROMISE_
  96. #include "CappuccinoPromise.h"
  97. #endif
  98.  
  99. #ifndef SOM_CappuccinoSI_xh
  100. #include "som_CappuccinoSI.xh"
  101. #endif
  102.  
  103. #ifndef _CAPPUCCINOUTILS_
  104. #include "CappuccinoUtils.h"
  105. #endif
  106.  
  107. #ifndef SOM_som_CappuccinoSettingsExtension_xh
  108. #include "som_CappuccinoSettingsExt.xh"
  109. #endif
  110.  
  111. #ifndef _SAMPLECOLLECTIONS_
  112. #include "SampleCollections.h"
  113. #endif
  114.  
  115. #ifndef _PRINTER_
  116. #include "Printer.h"
  117. #endif
  118.  
  119. #ifndef _TEMPFOCUS_
  120. #include "TempFocus.h"
  121. #endif
  122.  
  123. // -- OpenDoc Includes --
  124.  
  125. #ifndef _ODTYPES_
  126. #include <ODTypes.h>
  127. #endif
  128.  
  129. #ifndef SOM_ODArbitrator_xh
  130. #include <Arbitrat.xh>
  131. #endif
  132.  
  133. #ifndef SOM_ODCanvas_xh
  134. #include <Canvas.xh>
  135. #endif
  136.  
  137. #ifndef SOM_Module_OpenDoc_Commands_defined
  138. #include <CmdDefs.xh>
  139. #endif
  140.  
  141. #ifndef SOM_ODDraft_xh
  142. #include <Draft.xh>
  143. #endif
  144.  
  145. #ifndef SOM_ODFacet_xh
  146. #include <Facet.xh>
  147. #endif
  148.  
  149. #ifndef SOM_Module_OpenDoc_Foci_defined
  150. #include <Foci.xh>
  151. #endif
  152.  
  153. #ifndef SOM_ODFocusSet_xh
  154. #include <FocusSet.xh>
  155. #endif
  156.  
  157. #ifndef SOM_ODFrame_xh
  158. #include <Frame.xh>
  159. #endif
  160.  
  161. #ifndef SOM_ODFrameFacetIterator_xh
  162. #include <FrFaItr.xh>
  163. #endif
  164.  
  165. #ifndef SOM_ODMenuBar_xh
  166. #include <MenuBar.xh>
  167. #endif
  168.  
  169. #ifndef SOM_ODSession_xh
  170. #include <ODSessn.xh>
  171. #endif
  172.  
  173. #ifndef SOM_ODPart_xh
  174. #include <Part.xh>
  175. #endif
  176.  
  177. #ifndef SOM_ODShape_xh
  178. #include <Shape.xh>
  179. #endif
  180.  
  181. #ifndef SOM_Module_OpenDoc_StdDefs_defined
  182. #include <StdDefs.xh>
  183. #endif
  184.  
  185. #ifndef SOM_Module_OpenDoc_StandardExtensions_defined
  186. #include <StdExts.xh>
  187. #endif
  188.  
  189. #ifndef SOM_Module_OpenDoc_StdProps_defined
  190. #include <StdProps.xh>
  191. #endif
  192.  
  193. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  194. #include <StdTypes.xh>
  195. #endif
  196.  
  197. #ifndef SOM_ODStorageUnit_xh
  198. #include <StorageU.xh>
  199. #endif
  200.  
  201. #ifndef SOM_ODStorageUnitView_xh
  202. #include <SUView.xh>
  203. #endif
  204.  
  205. #ifndef SOM_ODTranslation_xh
  206. #include <Translt.xh>
  207. #endif
  208.  
  209. #ifndef SOM_ODTransform_xh
  210. #include <Trnsform.xh>
  211. #endif
  212.  
  213. #ifndef SOM_ODWindow_xh
  214. #include <Window.xh>
  215. #endif
  216.  
  217. #ifndef SOM_ODWindowState_xh
  218. #include <WinStat.xh>
  219. #endif
  220.  
  221. // -- OpenDoc Utilities --
  222.  
  223. #ifndef _BNDNSUTL_
  224. #include <BndNSUtl.h>
  225. #endif
  226.  
  227. #ifndef _DLOGUTIL_
  228. #include <DlogUtil.h>
  229. #endif
  230.  
  231. #ifndef _FOCUSLIB_
  232. #include <FocusLib.h>
  233. #endif
  234.  
  235. #ifndef _ISOSTR_
  236. #include <ISOStr.h>
  237. #endif
  238.  
  239. #ifndef _ITEXT_
  240. #include <IText.h>
  241. #endif
  242.  
  243. #ifndef _ODDEBUG_
  244. #include <ODDebug.h>
  245. #endif
  246.  
  247. #ifndef _ODMEMORY_
  248. #include <ODMemory.h>
  249. #endif
  250.  
  251. #ifndef _ODUTILS_
  252. #include <ODUtils.h>
  253. #endif
  254.  
  255. #ifndef _STDTYPIO_
  256. #include <StdTypIO.h>
  257. #endif
  258.  
  259. #ifndef _STORUTIL_
  260. #include <StorUtil.h>
  261. #endif
  262.  
  263. #ifndef _TEMPITER_
  264. #include <TempIter.h>
  265. #endif
  266.  
  267. #ifndef _TEMPOBJ_
  268. #include <TempObj.h>
  269. #endif
  270.  
  271. #ifndef _USERSRCM_
  272. #include <UseRsrcM.h>
  273. #endif
  274.  
  275. #ifndef _WINUTILS_
  276. #include <WinUtils.h>
  277. #endif
  278.  
  279. // -- Macintosh Includes --
  280.  
  281. #ifndef __DIALOGS__
  282. #include <Dialogs.h>
  283. #endif
  284.  
  285. #ifndef __ERRORS__
  286. #include <Errors.h>
  287. #endif
  288.  
  289. #ifndef __GXMATH__
  290. #include <GXMath.h>
  291. #endif
  292.  
  293. #ifndef __ICONS__
  294. #include <Icons.h>
  295. #endif
  296.  
  297. #ifndef __RESOURCES__
  298. #include <Resources.h>
  299. #endif
  300.  
  301. #ifndef __TOOLUTILS__
  302. #include <ToolUtils.h>
  303. #endif
  304.  
  305. #ifndef __QUICKDRAW__
  306. #include <Quickdraw.h>
  307. #endif
  308.  
  309. #ifndef __SPEECH__
  310. #include <Speech.h>
  311. #endif
  312.  
  313. #pragma segment Cappuccino
  314.  
  315. //==============================================================================
  316. // Cappuccino
  317. //==============================================================================
  318.  
  319. //==============================================================================
  320. #pragma mark    • Construction and Destruction •
  321. //==============================================================================
  322.  
  323. //------------------------------------------------------------------------------
  324. // Method:        CreatePartObject                                    [static]
  325. // Origin:        Cappuccino
  326. //
  327. // Description:    This static method is called by the SOM part object when it
  328. //                needs to create a new instance of this part.  This is done so
  329. //                that this function can be removed from here and implemented by
  330. //                a subclass to create an instance of the correct class.
  331. //------------------------------------------------------------------------------
  332.  
  333. Cappuccino* Cappuccino::CreatePartObject()
  334. {
  335.     return new Cappuccino;
  336. }
  337.  
  338. //------------------------------------------------------------------------------
  339. // Method:        Constructor
  340. // Origin:        Cappuccino
  341. //
  342. // Description:    This is the C++ class constructor.
  343. //
  344. // Warnings:    You are not allowed to throw an exception from this method.
  345. //------------------------------------------------------------------------------
  346.  
  347. Cappuccino::Cappuccino()
  348. {
  349.     SOM_Trace("Cappuccino","Constructor");
  350.     
  351.     fDisplayFrames            = kODNULL;
  352.     fSelf                    = kODNULL;
  353.  
  354.     fDirty                    = kODFalse;
  355.     fReadOnlyStorage        = kODFalse;
  356.     
  357.     fSettingsExtension        = kODNULL;
  358.     fSemanticInterface        = kODNULL;
  359.  
  360.     fPrinter                = kODNULL;
  361.     fHighlightedDragFacet    = kODNULL;
  362.     
  363.     fContent                = kODNULL;
  364.     fPreferredKind            = kODNULL;
  365.     
  366.     fSettings                = kODNULL;
  367. }
  368.  
  369. //------------------------------------------------------------------------------
  370. // Method:        Destructor
  371. // Origin:        Cappuccino
  372. //
  373. // Description:    This is the C++ class destructor.
  374. //
  375. // Warnings:    You are not allowed to throw an exception from this method.
  376. //------------------------------------------------------------------------------
  377.  
  378. Cappuccino::~Cappuccino()
  379. {
  380.     SOM_Trace("Cappuccino","Destructor");
  381. }
  382.  
  383. //==============================================================================
  384. #pragma mark    • Initialization •
  385. //==============================================================================
  386.  
  387. //------------------------------------------------------------------------------
  388. // Method:        InitPart
  389. // Origin:        ODPart
  390. //
  391. // Description:    This method is called when a new instance of this part is being
  392. //                created. The part should prepare itself to run.
  393. //
  394. // Parent:        The part's parent class was called before this method was
  395. //                dispatched to (see som_Cappuccino.cpp).
  396. //
  397. // Warning:        It is not appropriate to require user interaction while
  398. //                stationery is being created. Do not present the user with error
  399. //                dialogs or splash screens from this method.
  400. //------------------------------------------------------------------------------
  401.  
  402. void Cappuccino::InitPart( Environment*        ev,
  403.                            ODStorageUnit*    storageUnit,
  404.                            ODPart*            partWrapper )
  405. {
  406.     SOM_Trace("Cappuccino","InitPart");
  407.  
  408.     TRY
  409.         // To allow editor swapping (translation) at runtime, OpenDoc requires
  410.         // that we pass in a "reference" to ourselves when interacting with the
  411.         // API (eg. WindowState::RegisterWindow(), Dispatcher::RegisterIdle, etc).
  412.         // The "partWrapper" passed to us here and in InitPartFromStorage is the
  413.         // "reference" OpenDoc is asking us to use.
  414.         fSelf = partWrapper;
  415.     
  416.         // We are being created, either as part of generating stationery or
  417.         // by some editor instantiating the part, so the destination storage
  418.         // must be writeable.
  419.         fReadOnlyStorage = kODFalse;
  420.             
  421.         // Create the printer object.
  422.         fPrinter = CPrinter::New(ev, storageUnit);
  423.         
  424.         // Set up the default preferred kind.
  425.         fPreferredKind = kCappuccinoKind;
  426.  
  427.         // Call the common initialization code to get set up.
  428.         this->Initialize(ev);
  429.         
  430.         // Since we have just been created, our state/content info has
  431.         // never been written out, so setting our "dirty" flag will
  432.         // give us a chance to do that.
  433.         this->SetDirty(ev);
  434.     
  435.     CATCH_ALL
  436.         // Clean up will occur in the destructor which will be called
  437.         // shortly after we return the error.
  438.         RERAISE;
  439.     ENDTRY
  440. }
  441.  
  442. //------------------------------------------------------------------------------
  443. // Method:        InitPartFromStorage
  444. // Origin:        ODPart
  445. //
  446. // Description:    This method is called when a document/stationery is being opened
  447. //                or when the part is internalized by its containing part. The
  448. //                part should merely read in the saved state/content and
  449. //                initialize itself. The part must not alter its storage unit;
  450. //                otherwise, the "Save" menu item becomes enabled without the user
  451. //                actually having made a change to the document.
  452. //
  453. // Parent:        The part's parent class was called before this method was
  454. //                dispatched to (see som_Cappuccino.cpp).
  455. //------------------------------------------------------------------------------
  456.  
  457. void Cappuccino::InitPartFromStorage( Environment*        ev,
  458.                                       ODStorageUnit*    storageUnit,
  459.                                       ODPart*            partWrapper )
  460. {
  461.     SOM_Trace("Cappuccino","InitPartFromStorage");
  462.  
  463.     TRY
  464.         // To allow editor swapping (translation) at runtime, OpenDoc requires
  465.         // that we pass in a "reference" to ourselves when interacting with the
  466.         // API (eg. WindowState::RegisterWindow(), Dispatcher::RegisterIdle, etc).
  467.         // The "partWrapper" passed to us here and in InitPart is the
  468.         // "reference" OpenDoc is asking us to use.
  469.         fSelf = partWrapper;
  470.             
  471.         // Are we being opened from a read-only draft? If so, we cannot
  472.         // write anything back out to our storage unit.
  473.         fReadOnlyStorage = ( ODGetDraft(ev, storageUnit)->
  474.                                 GetPermissions(ev) < kODDPSharedWrite );
  475.             
  476.         // Create the printer object.
  477.         fPrinter = CPrinter::New(ev, storageUnit);
  478.  
  479.         // Call the common initialization code to get set up.
  480.         this->Initialize(ev);
  481.     
  482.         // Read in the state the part was in when it was last Externalized.
  483.         // This allows the part to present the same "environment" the user
  484.         // had the part set up in the last time it was edited.
  485.         this->InternalizeStateInfo(ev, storageUnit);
  486.     
  487.         // Read in the contents for your part editor.
  488.         this->InternalizeContent(ev, storageUnit);
  489.  
  490.     CATCH_ALL
  491.         // Clean up will occur in the destructor which will be called
  492.         // shortly after we return the error.
  493.         RERAISE;
  494.     ENDTRY
  495. }
  496.  
  497. //------------------------------------------------------------------------------
  498. // Method:        Initialize
  499. // Origin:        Cappuccino
  500. //
  501. // Description:    This method is called during the initialization of the part. The
  502. //                method is used to initialize all fields of the part and to
  503. //                convert ISO types to tokens for faster comparisons throughout
  504. //                the code.
  505. //
  506. //                If an exception is thrown in this method, it wil be propogated
  507. //                back to OpenDoc which will call our ReleaseAll() method and the
  508. //                class destructor. All memory allocated here will be cleaned up
  509. //                in the ReleaseAll() method.
  510. //------------------------------------------------------------------------------
  511.  
  512. void Cappuccino::Initialize( Environment*    ev )
  513. {
  514.     SOM_Trace("Cappuccino","Initialize");
  515.     
  516.     // Store the session in a member variable. This is merely for convenience.
  517.     fSession = ODGetSession(ev, fSelf);
  518.     
  519.     // Create our content object (we should have one at all times).
  520.     fContent = new CCappuccinoContent(this);
  521.     fContent->InitCappuccinoContent(ev);
  522.     
  523.     // Create our settings object to track part settings.
  524.     fSettings = new CSettings(this);
  525.     fSettings->InitSettings(ev);
  526.  
  527.     // Create a list to keep track of the frames we are being
  528.     // displayed in. Used for part maintenance (ie. Purging memory).
  529.     fDisplayFrames = new CList;
  530.  
  531.     // First check to see if the library's global variables have
  532.     // been initialized (meaning another part instantiation is already
  533.     // running).
  534.  
  535.     if ( gGlobalsUsageCount == 0 )
  536.     {
  537.         // Create our globals space. We store the globals in a struct so
  538.         // that we can put them in temp mem. Otherwise, CFM loads the globals
  539.         // with the data fragment of a CFM library in the application heap.
  540.         gGlobals = new CappuccinoGlobals;
  541.     
  542.         // We will be using the following foci (shared resources) in this
  543.         // part. For convenience, we tokenize the values here and store
  544.         // them for equivalence tests in the activation methods.
  545.         gGlobals->fSelectionFocus    = fSession->Tokenize(ev, kODSelectionFocus);
  546.         gGlobals->fMenuFocus        = fSession->Tokenize(ev, kODMenuFocus);
  547.         gGlobals->fModalFocus        = fSession->Tokenize(ev, kODModalFocus);
  548.     
  549.         // Also for convenience, we tokenize our part's main presentation
  550.         // and the standard view types.
  551.         gGlobals->fMainPresentation = fSession->Tokenize(ev, kMainPresentation);
  552.     
  553.         gGlobals->fFrameView     = fSession->Tokenize(ev, kODViewAsFrame);
  554.         gGlobals->fLargeIconView = fSession->Tokenize(ev, kODViewAsLargeIcon);
  555.         gGlobals->fSmallIconView = fSession->Tokenize(ev, kODViewAsSmallIcon);
  556.         gGlobals->fThumbnailView = fSession->Tokenize(ev, kODViewAsThumbnail);
  557.     
  558.         // This part supports TEXT data and files, so we must get the value types
  559.         // OpenDoc associates with each. We do this through the Translation object.
  560.         gGlobals->fTextDataValueType = fSession->GetTranslation(ev)->
  561.                         GetISOTypeFromPlatformType(ev, 'TEXT', kODPlatformDataType);
  562.         
  563.         // Value type for file information
  564.         gGlobals->fAppleHFSFlavorValueType = fSession->GetTranslation(ev)->
  565.                         GetISOTypeFromPlatformType(ev, 'hfs ', kODPlatformDataType);
  566.         
  567.         // Lastly, we will package the menu and selection focus
  568.         // so that we can request the "set" at activation time.
  569.         gGlobals->fUIFocusSet = fSession->GetArbitrator(ev)->CreateFocusSet(ev);
  570.         gGlobals->fUIFocusSet->Add(ev, gGlobals->fMenuFocus);
  571.         gGlobals->fUIFocusSet->Add(ev, gGlobals->fSelectionFocus);
  572.             
  573.         // If we wanted to support keyboard input (such as supporting F1 - F4 
  574.         // for undo, cut, copy, paste -- which aren't supported automatically
  575.         // by OpenDoc 1.0 -- or adding key input capability), we would need 
  576.         // to add a key focus for this, and we'd add it to our UI focus set.
  577.         
  578.         // Add our resource-based menus and register all the editor specific
  579.         // command numbers.
  580.         this->BuildMenuBar(ev);
  581.         
  582.         // Determine what Script/Language the part is localized for.
  583.         // This is important/necessary for creating OpenDoc's text objects.
  584.         GetEditorScriptLanguage(ev, &gGlobals->fEditorsScript, &gGlobals->fEditorsLanguage);
  585.         
  586.         // Create an object to track promises on the clipboard and drag & drop.
  587.         gGlobals->fClipboardPromises = new CPromiseSet;
  588.         gGlobals->fDragPromises = new CPromiseSet;
  589.         
  590.         // The first client of the global variables is running.
  591.         gGlobalsUsageCount = 1;
  592.     }
  593.     else
  594.     // If the globals have been initialized, we just bump the "usage" count so
  595.     // that we know how many part instances are using them.
  596.     {
  597.         gGlobalsUsageCount++;
  598.     }
  599. }
  600.  
  601. //==============================================================================
  602. #pragma mark    • Storage •
  603. //==============================================================================
  604.  
  605. //------------------------------------------------------------------------------
  606. // Method:        Release
  607. // Origin:        ODPart
  608. //
  609. // Description:    This method is called each time an object releases a reference
  610. //                to the part. If the refcount falls to 0, the part should
  611. //                release the fSelf part reference.
  612. //
  613. // Parent:        The part's parent class was called before this method was
  614. //                dispatched to (see som_Cappuccino.cpp).
  615. //
  616. // Warning:        If the part releases any other object when the refcount falls to
  617. //                zero, it will need to override the Acquire method so
  618. //                that the object can be referenced again if the parts refcount
  619. //                should be incremented before it is deleted.
  620. //------------------------------------------------------------------------------
  621.  
  622. void Cappuccino::Release( Environment* ev )
  623. {
  624.     SOM_Trace("Cappuccino","Release");
  625.  
  626.     if ( fSelf->GetRefCount(ev) == 0 )
  627.         ODGetDraft(ev, fSelf)->ReleasePart(ev, fSelf);
  628. }
  629.  
  630. //------------------------------------------------------------------------------
  631. // Method:        ReleaseAll
  632. // Origin:        ODPart
  633. //
  634. // Description:    This method is called just prior to the part being deleted by
  635. //                the Draft. The part must release all references to all
  636. //                refcounted objects it has stored internally; not doing so, will
  637. //                cause an "invalid ref count" exception/error at some later time.
  638. //
  639. // Parent:        The part's parent class will be called after this method
  640. //                returns (see som_Cappuccino.cpp).
  641. //------------------------------------------------------------------------------
  642.  
  643. void Cappuccino::ReleaseAll( Environment* ev )
  644. {
  645.     SOM_Trace("Cappuccino","ReleaseAll");
  646.  
  647.     TRY
  648.         // Release the content object.
  649.         if ( fContent )
  650.         {
  651.             fContent->Release();
  652.             fContent = kODNULL;
  653.         }
  654.         
  655.         // Release the settings object.
  656.         if ( fSettings )
  657.         {
  658.             fSettings->Release();
  659.             fSettings = kODNULL;
  660.         }
  661.         
  662.         // Delete the printer object.
  663.         ODDeleteObject(fPrinter);
  664.  
  665.         // Release our extensions.  Note: we can't use ODReleaseObject or     
  666.         // ODFinalReleaseObject here because they null out the field before the
  667.         // call to Release, but we need the field intact when ReleaseExtension is 
  668.         // called back upon the last reference being released.
  669.         ODRelease(ev, fSettingsExtension);
  670.         ODRelease(ev, fSemanticInterface);
  671.         
  672.         // If the last part instance using the globals is released,
  673.         // we need to clean up and delete the globals.
  674.         
  675.         if ( --gGlobalsUsageCount == 0 )
  676.         {
  677.             // But first, we need to delete the objects we created
  678.             // and stored in the globals struct.
  679.             ODDeleteObject(gGlobals->fUIFocusSet);
  680.             
  681.             // Dispose the memory used by our ISO strings.
  682.             ODDisposePtr(gGlobals->fTextDataValueType);
  683.             ODDisposePtr(gGlobals->fAppleHFSFlavorValueType);
  684.         
  685.             // We need to remove our menus from the menubar and dispose of
  686.             // them to free up their memory.
  687.             for (ODSShort index = 0; index < kNumMenus; index++)
  688.             {
  689.                 ODSShort id = kBaseMenuID + index;
  690.                 
  691.                 MenuHandle menu = gGlobals->fMenuBar->GetMenu(ev, id);
  692.                 gGlobals->fMenuBar->RemoveMenu(ev, id);
  693.                 if ( menu != kODNULL )
  694.                 {
  695.                     CUsingLibraryResources res;
  696.                     ReleaseResource((Handle) menu);
  697.                 }
  698.             }
  699.     
  700.             // Release the menubar.
  701.             ODReleaseObject(ev, gGlobals->fMenuBar);
  702.             
  703.             // Dispose the thumbnail picture.
  704.             if ( gGlobals->fThumbnail != kODNULL )
  705.                 ReleaseResource(gGlobals->fThumbnail);
  706.             
  707.             // Delete the object that tracks promises on the clipboard.
  708.             ODDeleteObject(gGlobals->fClipboardPromises);
  709.             ODDeleteObject(gGlobals->fDragPromises);
  710.  
  711.             // Now, clean up the globals struct.
  712.             ODDeleteObject(gGlobals);
  713.  
  714. #if ODDebug
  715.             // This is a debugging routine that checks to see if all of the ref-
  716.             // counted objects of ours have been released before this point.
  717.             CheckRefCountedObjects();
  718. #endif
  719.         }
  720.     
  721.         // Remove and release our display frames.
  722.         if ( fDisplayFrames )
  723.         {
  724.             CListIterator fiter(fDisplayFrames);
  725.             for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
  726.                     fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() )
  727.             {
  728.                 // Delete the proxy object and its contents. The frame's
  729.                 // refcount will be decremented in the proxy destructor.
  730.                 fiter.RemoveCurrent();
  731.                 delete proxy;
  732.             }
  733.         
  734.             // Delete the display frame collection.
  735.             ODDeleteObject(fDisplayFrames);
  736.         }
  737.         
  738.     CATCH_ALL
  739.         // If something goes wrong while we are cleaning up, we must
  740.         // let the Draft now because there may be some refcounted objects
  741.         // which did not get released. Not to mention, possible memory
  742.         // leaks.
  743.         RERAISE;            
  744.     ENDTRY
  745. }
  746.  
  747. //------------------------------------------------------------------------------
  748. // Method:        Purge
  749. // Origin:        ODPart
  750. //
  751. // Description:    This method is called when the OpenDoc requires more memory for
  752. //                allocating objects and just before a part is deleted. The part
  753. //                should free up as much memory as it can.
  754. //
  755. //                The part determines which views are being "used" in its display
  756. //                frames. The resources for the unused view types are then purged.
  757. //------------------------------------------------------------------------------
  758.  
  759. ODSize Cappuccino::Purge( Environment*    ev,
  760.                           ODSize        size )
  761. {
  762.     SOM_Trace("Cappuccino","Purge");
  763.  
  764.     // Purge is called during the creation of stationery. However,
  765.     // we have not created our internal display frames list, so 
  766.     // trying to iterate over it would be fatal.
  767.     if ( fDisplayFrames == kODNULL ) return 0;
  768.     
  769.     ODSize         bytesFreed        = 0;
  770.     ODBoolean    usingThumbnail  = kODFalse;
  771.     
  772.     // Iterate over the frames we are displayed through and determine which
  773.     // view types are currently in use.
  774.     
  775.     CListIterator fiter(fDisplayFrames);
  776.     for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
  777.             fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() )
  778.     {
  779.         // If the display frame is real (has been "connected" or was "added")
  780.         // get its view type; otherwise, ignore it.
  781.         if ( proxy->FrameIsLoaded(ev) )
  782.         {
  783.             ODTypeToken    frameView = proxy->GetFrame(ev)->GetViewType(ev);
  784.             
  785.             if ( frameView == gGlobals->fThumbnailView )
  786.                 usingThumbnail = kODTrue;
  787.             
  788.             // Release the frame reference, but don't get rid of the
  789.             // proxy object because we're not done with the frame. If
  790.             // all parts release their references the frame will be
  791.             // purged from memory.
  792.             proxy->Purge(ev);
  793.         }
  794.     }
  795.     
  796.     // Based on the usage of the supported view types, free up as much
  797.     // memory as possible.
  798.  
  799.     if ( !usingThumbnail && (gGlobals->fThumbnail != kODNULL) )
  800.     {
  801.         bytesFreed += (ODSize) ODGetHandleSize(gGlobals->fThumbnail);
  802.         ReleaseResource(gGlobals->fThumbnail);
  803.         gGlobals->fThumbnail = kODNULL;
  804.     }
  805.     
  806.     return bytesFreed;
  807. }
  808.  
  809. //------------------------------------------------------------------------------
  810. // Method:        InternalizeStateInfo
  811. // Origin:        Cappuccino
  812. //
  813. // Description:    This method is used to read in "state" information for the part.
  814. //                This is information related to the workings of the part editor,
  815. //                not the content.
  816. //
  817. //                The part writes out a list of weak references to its display
  818. //                frames. This allows the part to reuse the same display frames
  819. //                each time the document is opened. Those references are read
  820. //                back in and validated here.
  821. //
  822. // Note:        The function StorageUnitGetValue simplifies the use of
  823. //                ODByteArrary, which is required the StorageUnit interface. Look
  824. //                in StorUtil.h/cpp for an example of using the ODByteArray struct.
  825. //------------------------------------------------------------------------------
  826.  
  827. void Cappuccino::InternalizeStateInfo( Environment*        ev,
  828.                                        ODStorageUnit*    storageUnit )
  829. {
  830.     SOM_Trace("Cappuccino","InternalizeStateInfo");
  831.  
  832.     // Internalize annotation properties.
  833.     WASSERT(fSettings != kODNULL);
  834.     fSettings->Release();
  835.     fSettings = kODNULL;
  836.     
  837.     fSettings = new CSettings(this);
  838.     fSettings->InitSettings(ev, storageUnit);
  839.  
  840.     // Internalize the part's display frame list.
  841.     if ( ODSUExistsThenFocus(ev, storageUnit, kODPropDisplayFrames, kODWeakStorageUnitRefs) )
  842.     {
  843.         ODULong size = storageUnit->GetSize(ev);
  844.         storageUnit->SetOffset(ev, 0);    
  845.     
  846.         for ( ODULong offset = 0; offset < size; offset += kODStorageUnitRefSize )
  847.         {    
  848.             TRY    
  849.                 // We lazily internalize our display frames, meaning we don't "get"
  850.                 // the frame until we absolutely need it. This reduces the time
  851.                 // to internalize the part and the amount of memory needed.
  852.                     
  853.                 // Convert the reference into a runtime id.
  854.                 ODID frameID = ODGetWeakSURefProp(ev, storageUnit, kODNULL, kODNULL);
  855.                 if ( frameID != kODNULLID )
  856.                 {
  857.                     // Create a proxy class to support the lazy internalization.
  858.                     CFrameProxy* proxy = new CFrameProxy;
  859.                     proxy->InitFrameProxy(frameID, ODGetDraft(ev, storageUnit));
  860.                     
  861.                     // Add the proxy to the display frame collection.
  862.                     fDisplayFrames->Add(proxy);
  863.                 }
  864.             CATCH_ALL
  865.                 // consume exception
  866.             ENDTRY
  867.         }
  868.     }
  869. }
  870.  
  871. //------------------------------------------------------------------------------
  872. // Method:        InternalizeContent
  873. // Origin:        Cappuccino
  874. //
  875. // Description:    This method is called during initialization of the part from an
  876. //                existing document. The content of the part should be read in.
  877. //
  878. //                The part has no intrinsic content, so the part does nothing.
  879. //                The method is here for completeness.
  880. //------------------------------------------------------------------------------
  881.  
  882. void Cappuccino::InternalizeContent( Environment*        ev,
  883.                                      ODStorageUnit*        storageUnit )
  884. {
  885.     SOM_Trace("Cappuccino","InternalizeContent");
  886.     
  887.     WASSERT(fContent != kODNULL);
  888.     fContent->Release();
  889.     fContent = kODNULL;
  890.     
  891.     fContent = new CCappuccinoContent(this);
  892.     fContent->InitCappuccinoContent(ev, storageUnit);
  893.  
  894.     // If we don't have a preferred kind yet, use the kind that was found, 
  895.     // if any.  Otherwise, use our default kind.
  896.     if ( fPreferredKind == kODNULL )
  897.     {
  898.         // This is actually a little wasteful, as this kind was just determined
  899.         // by InitCappuccinoContent, but that routine doesn't return it to us,
  900.         // so we have to calculate it again.  This is one of several optimization
  901.         // opportunities.
  902.         ODValueType kindToUse = CCappuccinoContent::GetKindToInternalize(ev, storageUnit);
  903.         fPreferredKind = (kindToUse != kODNULL) ? kindToUse : kCappuccinoKind;
  904.     }
  905. }
  906.  
  907. //------------------------------------------------------------------------------
  908. // Method:        CloneInto
  909. // Origin:        ODPart
  910. //
  911. // Description:    This method is called during cloning, typically during data
  912. //                interchange operations (eg. Cut/Paste). The part should
  913. //                write out its current state and content.
  914. //
  915. // Parent:        The part's parent class was called before this method was
  916. //                dispatched to (see som_Cappuccino.cpp).
  917. //------------------------------------------------------------------------------
  918.  
  919. void Cappuccino::CloneInto( Environment*        ev,
  920.                             ODDraftKey            key,
  921.                             ODStorageUnit*        destinationSU,
  922.                             ODFrame*            initiatingFrame )
  923. {
  924.     SOM_Trace("Cappuccino","CloneInto");
  925.     
  926.     // We must first verify that we've never written to this storage unit.
  927.     // If we have, we should do nothing, otherwise we need to write out
  928.     // the current state of the part content.
  929.     
  930.     // To do this, we call CCappuccinoContent::HasSupportedKind, which will 
  931.     // return kODFalse if there are no recognized types in the storage unit.
  932.     
  933.     if ( !fContent->HasSupportedKind(ev, destinationSU) )
  934.     {
  935.         // Add the properties we need to successfully externalize
  936.         // ourselves into the destination storage unit.
  937.         this->CheckAndAddProperties(ev, destinationSU);
  938.                 
  939.         // Write out the part's state information.
  940.         this->ExternalizeStateInfo(ev, destinationSU, key, initiatingFrame);
  941.             
  942.         // Write out the part's content.
  943.         this->ExternalizeContent(ev, destinationSU, key, initiatingFrame);
  944.     }
  945. }
  946.  
  947. //------------------------------------------------------------------------------
  948. // Method:        Externalize
  949. // Origin:        ODPart
  950. //
  951. // Description:    This method is called when the user saves the document. The part
  952. //                should write out its state and content if changes have occurred
  953. //                and if our storage is writeable.
  954. //
  955. // Parent:        The part's parent class was called before this method was
  956. //                dispatched to (see som_Cappuccino.cpp).
  957. //------------------------------------------------------------------------------
  958.  
  959. void Cappuccino::Externalize( Environment* ev )
  960. {
  961.     SOM_Trace("Cappuccino","Externalize");
  962.  
  963.     TRY
  964.         if ( fDirty && !fReadOnlyStorage )
  965.         {
  966.             // Get our storage unit.
  967.             ODStorageUnit* storageUnit = fSelf->GetStorageUnit(ev);
  968.         
  969.             // Verify that the storage unit has the appropriate properties
  970.             // and values to allow us to run. If not, add them.
  971.             this->CheckAndAddProperties(ev, storageUnit);
  972.         
  973.             // Verify that there are no "bogus" values in the Content
  974.             // property.
  975.             this->CleanseContentProperty(ev, storageUnit);
  976.         
  977.             // Write out the part's state information.
  978.             this->ExternalizeStateInfo(ev, storageUnit, kODNULLKey, kODNULL);
  979.                 
  980.             // Write out the part's content.
  981.             this->ExternalizeContent(ev, storageUnit, kODNULLKey, kODNULL);
  982.     
  983.             // Flag our part as no longer being dirty.
  984.             fDirty = kODFalse;
  985.         }
  986.  
  987.         // PRINTING: Externalize the page setup info. It might be dirty even 
  988.         // if fDirty is false, so don't put this in the if block above.
  989.         if ( !fReadOnlyStorage && fPrinter ) 
  990.         {
  991.             TRY
  992.                 fPrinter->Externalize(ev);
  993.             CATCH_ALL
  994.                 WARN("Err %d externalizing page setup", ErrorCode());
  995.             ENDTRY
  996.         }
  997.     CATCH_ALL
  998.         // Alert the user of the problem.
  999.         this->DoDialogBox(ev, kODNULL, kErrorBoxID, kErrExternalizeFailed);
  1000.         // Change the exception value, so the DocShell doesn't display an
  1001.         // error dialog.
  1002.         SetErrorCode(kODErrAlreadyNotified);
  1003.         // Alert the caller.
  1004.         RERAISE;
  1005.     ENDTRY
  1006. }
  1007.  
  1008. //------------------------------------------------------------------------------
  1009. // Method:        ExternalizeKinds
  1010. // Origin:        ODPart
  1011. //
  1012. // Description:    This method is called when the user wants to save the document
  1013. //                with multiple representations of the data. This is especially
  1014. //                useful for increasing the portability of documents
  1015. //                cross-platform.
  1016. //
  1017. //                A part should verify each kind is valid, that it exists in
  1018. //                the content property in the correct order, and write the data.
  1019. //
  1020. // Note:        For parts which support only on kind, the code can simplified.
  1021. //                In this case, it is not necessary to iterate over the kindset
  1022. //                because you must, at least, write your preferred kind. The code
  1023. //                is shown this way to better illustrate the recipe; it is not
  1024. //                wrong, it just does more than it needs to.
  1025. //------------------------------------------------------------------------------
  1026.  
  1027. void Cappuccino::ExternalizeKinds( Environment*        ev, 
  1028.                                    ODTypeList*        kindset )
  1029. {
  1030.     WASSERT(fContent != kODNULL);
  1031.  
  1032.     if ( !fReadOnlyStorage )
  1033.     {
  1034.         ODBoolean preferredKindWritten = kODFalse;
  1035.         
  1036.         // Get our storage unit.
  1037.         ODStorageUnit* storageUnit = fSelf->GetStorageUnit(ev);
  1038.         
  1039.         // Verify that the storage unit has the appropriate properties
  1040.         // and values to allow us to run. If not, add them.
  1041.         this->CheckAndAddProperties(ev, storageUnit);
  1042.     
  1043.         // Verify that there are no "bogus" values in the Content
  1044.         // property.
  1045.         this->CleanseContentProperty(ev, storageUnit);
  1046.     
  1047.         // Iterate over the kindset and write out the content types
  1048.         // that we support.
  1049.         TempODTypeListIterator iter(ev, kindset);
  1050.         for ( ODType kind = iter.First(); iter.IsNotComplete(); kind = iter.Next() )
  1051.         {
  1052.             // Check to see if this is a kind we support. If so, write it.
  1053.             if ( fContent->IsKindSupported(ev, kind) )
  1054.             {
  1055.                 // Write out the part's content.
  1056.                 fContent->ExternalizeOneKind(ev, storageUnit, kODNULLKey, kind);
  1057.                 
  1058.                 // This is our preferrend kind so we don't need to write it again.
  1059.                 // Part editors with more than one kind need to test each kind
  1060.                 // against the preferred kind to make sure it's been written.
  1061.                 if ( ODISOStrEqual(kind, fPreferredKind) )
  1062.                     preferredKindWritten = kODTrue;
  1063.             }
  1064.         }
  1065.     
  1066.         // Write out the part's state information.
  1067.         this->ExternalizeStateInfo(ev, storageUnit, kODNULLKey, kODNULL);
  1068.  
  1069.         // Even if the kind set contains no types we support, we must at least
  1070.         // write out our current "preferred" kind.
  1071.         if ( preferredKindWritten == kODFalse )
  1072.         {
  1073.             // Write out the part's preferred content kind.
  1074.             fContent->ExternalizeOneKind(ev, storageUnit, kODNULLKey, fPreferredKind);
  1075.         }
  1076.     }
  1077. }
  1078.  
  1079. //------------------------------------------------------------------------------
  1080. // Method:        ChangeKind
  1081. // Origin:        ODPart
  1082. //
  1083. // Description:    This method is called when the changes the part's primary kind
  1084. //                and/or when the part editor is switched via the Info dialog.
  1085. //
  1086. //                The editor should record the new "preferred" kind and change the
  1087. //                UI, if necessary, to allow editing of that kind. Don't write the
  1088. //                properties/values/data until the Externalize is called.
  1089. //------------------------------------------------------------------------------
  1090.  
  1091. void Cappuccino::ChangeKind( Environment*    ev,
  1092.                              ODType            kind )
  1093. {
  1094.     if ( fContent->IsKindSupported(ev, kind) )
  1095.     {
  1096.         if ( !ODISOStrEqual(kind, fPreferredKind) )
  1097.         {
  1098.             fPreferredKind = fContent->RecoverKindPtr(ev, kind);
  1099.     
  1100.             // Get our storage unit.
  1101.             ODStorageUnit* storageUnit = fSelf->GetStorageUnit(ev);
  1102.             
  1103.             // Write out the users preferred kind.
  1104.             SetPreferredKind(ev, storageUnit, fPreferredKind);
  1105.             
  1106.             // Changing our kind dirties our content.
  1107.             this->SetDirty(ev);
  1108.                 
  1109.             // Immediately externalize ourselves in the "new" format.
  1110.             this->Externalize(ev);
  1111.         }
  1112.     }
  1113.     else
  1114.     {
  1115.         THROW(kODErrInvalidValueType);
  1116.     }
  1117. }
  1118.  
  1119. //------------------------------------------------------------------------------
  1120. // Method:        ExternalizeStateInfo
  1121. // Origin:        Cappuccino
  1122. //
  1123. // Description:    This method is called during externalization of the part. The
  1124. //                current "state" of the part should be written out. This "state"
  1125. //                information may be lost during Data Interchange operations, so
  1126. //                the part needs to recover gracefully if information is missing
  1127. //                or incomplete.
  1128. //
  1129. // Note:        The function StorageUnitSetValue is a macro which simplifies
  1130. //                the use of ODByteArrary, which is required by the StorageUnit
  1131. //                interface. Look in StorUtil.h/cpp for an example of using the
  1132. //                ODByteArray struct.
  1133. //------------------------------------------------------------------------------
  1134.  
  1135. void Cappuccino::ExternalizeStateInfo( Environment*        ev,
  1136.                                        ODStorageUnit*    storageUnit,
  1137.                                        ODDraftKey        key,
  1138.                                        ODFrame*            scopeFrame )
  1139. {
  1140.     SOM_Trace("Cappuccino","ExternalizeStateInfo");
  1141.  
  1142.     // Externalize the font and size into annotation properties.
  1143.     WASSERT(fSettings != kODNULL);
  1144.     fSettings->Externalize(ev, storageUnit);
  1145.     
  1146.     // Externalize the page setup info. 
  1147.     // Note: This is also done in the Externalize method; it's repeated here so 
  1148.     // it will happen even on a clone operation.
  1149.     if ( fPrinter ) 
  1150.     {
  1151.         TRY
  1152.             fPrinter->Externalize(ev, storageUnit);
  1153.         CATCH_ALL
  1154.             WARN("Err %d externalizing page setup", ErrorCode());
  1155.         ENDTRY
  1156.     }
  1157.     
  1158.     // Set up the preferred kind property with our preferred kind.
  1159.     SetPreferredKind(ev, storageUnit, fPreferredKind);
  1160.         
  1161.     // Externalize the part's display frame list.
  1162.     storageUnit->Focus(ev, kODPropDisplayFrames, kODPosUndefined,
  1163.                        kODWeakStorageUnitRefs, 0, kODPosUndefined);
  1164.     
  1165.     // Persistent object references are stored in a side table, rather than
  1166.     // in the property/value stream. Thus, deleting the contents of a value
  1167.     // will not "delete" the references previously written to that value. To
  1168.     // completely "delete" all references written to the value, we must
  1169.     // remove the value and add it back.
  1170.     storageUnit->Remove(ev);
  1171.     storageUnit->AddValue(ev, kODWeakStorageUnitRefs);
  1172.  
  1173.     ODID        scopeFrameID = ( scopeFrame ? scopeFrame->GetID(ev) : kODNULLID );
  1174.     ODDraft*    fromDraft = ODGetDraft(ev, fSelf);
  1175.     
  1176.     CListIterator fiter(fDisplayFrames);
  1177.     for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
  1178.             fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() )
  1179.     {
  1180.         // Get the ID of the frame we are going to weakly reference.
  1181.         ODID frameID = proxy->GetID();
  1182.         
  1183.         // If a draft key exists, then we are being cloned to another draft.
  1184.         // We must "weak" clone our display frame and reference the cloned
  1185.         // frame. The part re-uses the frameID variable so there aren't two
  1186.         // different GetWeakStorageUnitRef calls.
  1187.         if ( key )
  1188.             frameID = fromDraft->WeakClone(ev, key, frameID, kODNULLID, scopeFrameID);
  1189.         
  1190.         TRY
  1191.             ODSetWeakSURefProp(ev, storageUnit, kODNULL, kODNULL, frameID);
  1192.         CATCH_ALL
  1193.             // consume the exception
  1194.         ENDTRY
  1195.     }
  1196. }
  1197.  
  1198. //------------------------------------------------------------------------------
  1199. // Method:        ExternalizeContent
  1200. // Origin:        Cappuccino
  1201. //
  1202. // Description:    This method is called during exteralization of the part. The
  1203. //                content of the part should be written out.
  1204. //------------------------------------------------------------------------------
  1205.  
  1206. void Cappuccino::ExternalizeContent( Environment*        ev,
  1207.                                      ODStorageUnit*        storageUnit,
  1208.                                      ODDraftKey            key,
  1209.                                      ODFrame*            scopeFrame )
  1210. {
  1211.     SOM_Trace("Cappuccino","ExternalizeContent");
  1212.     
  1213.     WASSERT(fContent != kODNULL);
  1214.     fContent->Externalize(ev, storageUnit, key);
  1215. }
  1216.  
  1217. //------------------------------------------------------------------------------
  1218. // Method:        CleanseContentProperty
  1219. // Origin:        Cappuccino
  1220. //
  1221. // Description:    This method is called during exteralization of the part so that
  1222. //                the part can remove any value in the content property
  1223. //                that it cannot "accurately" write to.
  1224. //
  1225. // Note:        "Additional" values will be added to a part's content property
  1226. //                during Drag & Drop operations.
  1227. //------------------------------------------------------------------------------
  1228.  
  1229. void Cappuccino::CleanseContentProperty( Environment*        ev,
  1230.                                          ODStorageUnit*        storageUnit )
  1231. {
  1232.     SOM_Trace("Cappuccino","CleanseContentProperty");
  1233.     
  1234.     WASSERT(fContent != kODNULL);
  1235.     fContent->Prepare(ev, storageUnit, fPreferredKind);
  1236. }
  1237.  
  1238. //------------------------------------------------------------------------------
  1239. // Method:        CheckAndAddProperties
  1240. // Origin:        Cappuccino
  1241. //
  1242. // Description:    This method is called during externalization of the part to
  1243. //                verify that all the properties needed to persistently represent
  1244. //                the current running state of the part.
  1245. //
  1246. //                The part adds the default content property, a preferred editor
  1247. //                property (to aid in part binding), and a display frames
  1248. //                property.
  1249. //
  1250. // Note:        The function StorageUnitSetValue is a macro which simplifies
  1251. //                the use of ODByteArrary, which is required the StorageUnit
  1252. //                interface. Look in StorUtil.h/cpp for an example of using the
  1253. //                ODByteArray struct.
  1254. //------------------------------------------------------------------------------
  1255.  
  1256. void Cappuccino::CheckAndAddProperties( Environment*    ev,
  1257.                                         ODStorageUnit*    storageUnit )
  1258. {
  1259.     SOM_Trace("Cappuccino","CheckAndAddProperties");
  1260.  
  1261.     // Create our content property and preferred content property kind.
  1262.     ODSUForceFocus(ev, storageUnit, kODPropContents, fPreferredKind);
  1263.  
  1264.     // Since we are setting up the preferred kind property, we just write
  1265.     // out our default "kind" for the editor. We can write out the user
  1266.     // chosen kind in the ExternalizeStateInfo method.
  1267.     if ( !storageUnit->Exists(ev, kODPropPreferredKind, kODISOStr, 0) )
  1268.         SetPreferredKind(ev, storageUnit, kCappuccinoKind);
  1269.         
  1270.     // Add our display frame list.    
  1271.     ODSUForceFocus(ev, storageUnit, kODPropDisplayFrames, kODWeakStorageUnitRefs);
  1272. }
  1273.  
  1274. //------------------------------------------------------------------------------
  1275. // Method:        SetDirty
  1276. // Origin:        Cappuccino
  1277. //
  1278. // Description:    This method is called by the part when the content or state of
  1279. //                the part has been modified by the user and the "Save" menu item
  1280. //                should be enabled.
  1281. //------------------------------------------------------------------------------
  1282.  
  1283. void Cappuccino::SetDirty( Environment*    ev )
  1284. {
  1285.     SOM_Trace("Cappuccino","SetDirty");
  1286.  
  1287.     // There is no need to repeatedly tell the draft we have changed;
  1288.     // once is sufficient.
  1289.     if ( !fDirty && !fReadOnlyStorage )
  1290.     {
  1291.         fDirty = kODTrue;
  1292.         ODGetDraft(ev, fSelf)->SetChangedFromPrev(ev);
  1293.     }
  1294. }
  1295.  
  1296. //------------------------------------------------------------------------------
  1297. // Method:        ReadPartInfo
  1298. // Origin:        ODPart
  1299. //
  1300. // Description:    When a frame is being internalized by the Draft, it will ask the
  1301. //                owner (part) to read in its info annotation on the frame.
  1302. //
  1303. //                The part uses a C++ helper class to encapsulate the information
  1304. //                we store with each frame, so we let it internalize itself from
  1305. //                the storage unit view.
  1306. //------------------------------------------------------------------------------
  1307.  
  1308. ODInfoType Cappuccino::ReadPartInfo( Environment*        ev,
  1309.                                      ODFrame*            frame,
  1310.                                      ODStorageUnitView*    storageUnitView )
  1311. {
  1312.     SOM_Trace("Cappuccino","ReadPartInfo");
  1313.  
  1314.     CFrameInfo* frameInfo = this->CreateFrameInfo(ev, frame);
  1315.         
  1316.     TRY
  1317.         // Ask the info class to internalize itself.
  1318.         frameInfo->InitFromStorage(ev, storageUnitView);
  1319.     CATCH_ALL
  1320.         // Clean up the allocated memory.
  1321.         ODDeleteObject(frameInfo);
  1322.         // Alert the caller.
  1323.         RERAISE;
  1324.     ENDTRY
  1325.     
  1326.     return (ODInfoType) frameInfo;
  1327. }
  1328.  
  1329. //------------------------------------------------------------------------------
  1330. // Method:        WritePartInfo
  1331. // Origin:        ODPart
  1332. //
  1333. // Description:    When a frame is being externalized by the Draft, it will ask the
  1334. //                owner (part) to write out its info annotation on the frame.
  1335. //
  1336. //                The part uses a C++ helper class to encapsulate the information
  1337. //                we store with each frame, so we let it externalize itself to
  1338. //                the storage unit view.
  1339. //------------------------------------------------------------------------------
  1340.  
  1341. void Cappuccino::WritePartInfo( Environment*        ev,
  1342.                                   ODInfoType            partInfo,
  1343.                                 ODStorageUnitView*    storageUnitView )
  1344. {
  1345.     SOM_Trace("Cappuccino","WritePartInfo");
  1346.     
  1347.     ASSERT_NOT_NULL(partInfo);
  1348.  
  1349.     // Tell our frame info class to write itself out into the pre-
  1350.     // focused storage unit.
  1351.     ((CFrameInfo*) partInfo)->Externalize(ev, storageUnitView);
  1352. }
  1353.  
  1354. //------------------------------------------------------------------------------
  1355. // Method:        ClonePartInfo
  1356. // Origin:        ODPart
  1357. //
  1358. // Description:    When a frame is being cloned by the Draft, it will ask the owner
  1359. //                (part) to clone its info annotation on the frame.
  1360. //
  1361. //                The part uses a C++ helper class to encapsulate the information
  1362. //                we store with each frame, so we let it clone itself to the
  1363. //                storage unit view.
  1364. //------------------------------------------------------------------------------
  1365.  
  1366. void Cappuccino::ClonePartInfo( Environment*        ev,
  1367.                                 ODDraftKey            key,
  1368.                                   ODInfoType            partInfo,
  1369.                                 ODStorageUnitView*    storageUnitView,
  1370.                                 ODFrame*            scopeFrame )
  1371. {
  1372.     SOM_Trace("Cappuccino","ClonePartInfo");
  1373.     
  1374.     ASSERT_NOT_NULL(partInfo);
  1375.  
  1376.     // Tell our frame info class to write itself out into the pre-
  1377.     // focused storage unit.
  1378.     ((CFrameInfo*) partInfo)->CloneInto(ev, key, storageUnitView, scopeFrame);
  1379. }
  1380.  
  1381. //------------------------------------------------------------------------------
  1382. // Method:        SetContent
  1383. // Origin:        Cappuccino
  1384. //
  1385. // Description:    This method is called when the content of the part should be
  1386. //                changed to the new content object.  This function will then
  1387. //                set the part to be dirty, notify the frames that the content
  1388. //                has been updated, and invalidate the frames so that they will
  1389. //                be redrawn with the new content.
  1390. //------------------------------------------------------------------------------
  1391.  
  1392. void Cappuccino::SetContent( Environment*            ev,
  1393.                              CCappuccinoContent*    newContent )
  1394. {
  1395.     if ( newContent )
  1396.         newContent->Acquire();
  1397.     
  1398.     TRY
  1399.         if ( fContent )
  1400.             fContent->Release();
  1401.     CATCH_ALL
  1402.         if ( newContent )
  1403.             newContent->Release();
  1404.         RERAISE;
  1405.     ENDTRY
  1406.     
  1407.     fContent = newContent;
  1408.     
  1409.     // Set the part dirty and cause all of the necessary frames to get redrawn.
  1410.     this->HandleChange(ev);
  1411. }
  1412.  
  1413. //------------------------------------------------------------------------------
  1414. // Method:        SetSettings
  1415. // Origin:        Cappuccino
  1416. //
  1417. // Description:    This method is called when the settings of the part should be
  1418. //                changed to the new contents.  This function will then set the 
  1419. //                part to be dirty, notify the frames that the content has been 
  1420. //                updated, and invalidate the frames so that they will be 
  1421. //                redrawn with the new content.
  1422. //------------------------------------------------------------------------------
  1423.  
  1424. void Cappuccino::SetSettings( Environment*        ev,
  1425.                               CSettings*        newSettings )
  1426. {
  1427.     if ( newSettings )
  1428.         newSettings->Acquire();
  1429.     
  1430.     TRY
  1431.         if ( fSettings )
  1432.             fSettings->Release();
  1433.     CATCH_ALL
  1434.         if ( newSettings )
  1435.             newSettings->Release();
  1436.         RERAISE;
  1437.     ENDTRY
  1438.     
  1439.     fSettings = newSettings;
  1440.     
  1441.     // Set the part dirty and cause all of the necessary frames to get redrawn.
  1442.     this->HandleChange(ev);
  1443. }
  1444.  
  1445. //------------------------------------------------------------------------------
  1446. // Method:        HandleChange
  1447. // Origin:        Cappuccino
  1448. //
  1449. // Description:    This method is called when the content of the part or some
  1450. //                other information has changed such that we need to redraw our
  1451. //                content, mark our frames as updated, and set the part to be
  1452. //                dirty.
  1453. //------------------------------------------------------------------------------
  1454.  
  1455. void Cappuccino::HandleChange( Environment* ev )
  1456. {
  1457.     this->SetDirty(ev);
  1458.     this->ContentUpdated(ev);
  1459.     this->InvalidateFrameViews(ev);
  1460. }
  1461.  
  1462. //==============================================================================
  1463. #pragma mark    • Extensions •
  1464. //==============================================================================
  1465.  
  1466. //------------------------------------------------------------------------------
  1467. // Method:        HasExtension
  1468. // Origin:        ODPart
  1469. //
  1470. // Description:    The method is called when something wants to know if this
  1471. //                part supports a particular type of extension.
  1472. //------------------------------------------------------------------------------
  1473.  
  1474. ODBoolean Cappuccino::HasExtension( Environment*    ev,
  1475.                                     ODType            extensionName )
  1476. {
  1477.     SOM_Trace("Cappuccino","HasExtension");
  1478.     
  1479. #ifndef qViewerBuild
  1480.     // We don't want to include our settings extension if we're in a read only
  1481.     // storage unit, because we can't allow changing of the settings in that case.
  1482.     return ( (ODISOStrEqual(extensionName, kODSettingsExtension) && !fReadOnlyStorage)
  1483.           || ODISOStrEqual(extensionName, kODExtSemanticInterface) );
  1484. #else
  1485.     return ( ODISOStrEqual(extensionName, kODExtSemanticInterface) );
  1486. #endif
  1487. }
  1488.  
  1489. //------------------------------------------------------------------------------
  1490. // Method:        AcquireExtension
  1491. // Origin:        ODPart
  1492. //
  1493. // Description:    The method is called when the part is being asked for
  1494. //                a particular extension.
  1495. //------------------------------------------------------------------------------
  1496.  
  1497. ODExtension* Cappuccino::AcquireExtension( Environment*        ev,
  1498.                                            ODType            extensionName )
  1499. {
  1500.     SOM_Trace("Cappuccino","AcquireExtension");
  1501.  
  1502. #ifndef qViewerBuild
  1503.     if ( ODISOStrEqual(extensionName, kODSettingsExtension) )
  1504.     {
  1505.         if ( fSettingsExtension == kODNULL )
  1506.         {
  1507.             fSettingsExtension = new som_CappuccinoSettingsExtension;
  1508.             THROW_IF_NULL(fSettingsExtension);
  1509.             fSettingsExtension->InitSettingsExtension(ev, fSelf);
  1510.         }
  1511.  
  1512.         ODAcquireObject(ev, fSettingsExtension);
  1513.         return fSettingsExtension;
  1514.     }
  1515. #endif
  1516.     
  1517.     if ( ODISOStrEqual(extensionName, kODExtSemanticInterface) )
  1518.     {
  1519.         if ( fSemanticInterface == kODNULL )
  1520.         {
  1521.             this->ConstructSemanticInterface(ev);
  1522.         }
  1523.  
  1524.         ODAcquireObject(ev, fSemanticInterface);    
  1525.         return fSemanticInterface;
  1526.     }
  1527.  
  1528.     return kODNULL;    
  1529. }
  1530.  
  1531. //------------------------------------------------------------------------------
  1532. // Method:        ReleaseExtension
  1533. // Origin:        ODPart
  1534. //
  1535. // Description:    The method is called when the last instance of an extension
  1536. //                belonging to this part has been released.
  1537. //
  1538. //                NOTE: This routine, unlike it's SOM counterpart, returns a
  1539. //                Boolean value indicating whether the extension was one we knew
  1540. //                about.  If not (and only if not), the SOM class must call the 
  1541. //                parent class to see if it knows about the extension.
  1542. //------------------------------------------------------------------------------
  1543.  
  1544. ODBoolean Cappuccino::ReleaseExtension( Environment*    ev,
  1545.                                         ODExtension*     extension )
  1546. {
  1547.     SOM_Trace("Cappuccino","ReleaseExtension");
  1548.  
  1549. #ifndef qViewerBuild
  1550.     if ( ODObjectsAreEqual(ev, extension, fSettingsExtension) )
  1551.     {
  1552.         ODDeleteObject(fSettingsExtension);
  1553.         return kODTrue;
  1554.     }
  1555. #endif
  1556.     
  1557.     if ( ODObjectsAreEqual(ev, extension, fSemanticInterface) )
  1558.     {
  1559.         ODDeleteObject(fSemanticInterface);
  1560.         return kODTrue;
  1561.     }
  1562.  
  1563.     return kODFalse;
  1564. }
  1565.  
  1566. //==============================================================================
  1567. #pragma mark    • Layout •
  1568. //==============================================================================
  1569.  
  1570. //------------------------------------------------------------------------------
  1571. // Method:        DisplayFrameAdded
  1572. // Origin:        ODPart
  1573. //
  1574. // Description:    This method is called in response to a frame being created for
  1575. //                the part.
  1576. //
  1577. //                The part records the existence of a new display frame in its
  1578. //                internal display frame list, as well as, verifies that the frame
  1579. //                is "set up" correctly (ie. valid viewType). The part also
  1580. //                creates and stores its "frame info" class in the new frame. 
  1581. //------------------------------------------------------------------------------
  1582.  
  1583. void Cappuccino::DisplayFrameAdded( Environment*    ev,
  1584.                                        ODFrame*        frame )
  1585. {
  1586.     SOM_Trace("Cappuccino","DisplayFrameAdded");
  1587.  
  1588.     ASSERT_NOT_NULL(frame);
  1589.  
  1590.     // If we are being embedded in another part, the presentation field
  1591.     // will (most likely) be unset; we need to set it something meaningful.
  1592.     // The view field may also be unset, if so, we prefer to be displayed
  1593.     // in a frame view.
  1594.     if ( frame->GetPresentation(ev) != gGlobals->fMainPresentation )
  1595.         frame->SetPresentation(ev, gGlobals->fMainPresentation);
  1596.     
  1597.     if ( frame->GetViewType(ev) == kODNullTypeToken )
  1598.         frame->SetViewType(ev, gGlobals->fFrameView);
  1599.         
  1600.     // Hang our "state" info off of the new display frame. We use
  1601.     // the CFrameInfo object for activation, updating, and window
  1602.     // maintenance.
  1603.     CFrameInfo* frameInfo = this->CreateFrameInfo(ev, frame);
  1604.     frame->SetPartInfo(ev, (ODInfoType) frameInfo);
  1605.     
  1606.     // If the frame being added is a root frame, we know that a window
  1607.     // is associated with this frame. Notify ourselves that we need to 
  1608.     // clean it up when the frame goes away.
  1609.     if ( frame->IsRoot(ev) )
  1610.         frameInfo->SetShouldDisposeWindow(kODTrue);
  1611.     
  1612.     // The proxy class will refcount the frame passed to it, so we
  1613.     // don't need to worry about refcounting the display frame.
  1614.     CFrameProxy* proxy = new CFrameProxy;
  1615.     proxy->InitFrameProxy(ev, frame);
  1616.  
  1617.     // Add the proxy to the display frame collection.
  1618.     fDisplayFrames->Add(proxy);
  1619.     
  1620. #ifndef qViewerBuild
  1621.     // Since we support drag-and-drop, turn it on.
  1622.     frame->SetDroppable(ev, kODTrue);
  1623. #endif
  1624.     
  1625.     // Since we maintain a persistent list of weak references to our
  1626.     // display frames, having one added to the part dirties it, but only
  1627.     // if the frame is persistent.
  1628.     if ( frame->GetStorageUnit(ev) != kODNULL )
  1629.         this->SetDirty(ev);
  1630. }
  1631.  
  1632. //------------------------------------------------------------------------------
  1633. // Method:        DisplayFrameConnected
  1634. // Origin:        ODPart
  1635. //
  1636. // Description:    This method is called when one of our display frames, previously
  1637. //                written out, is internalized. This method is called instead of
  1638. //                DisplayFrameAdded because a "new" frame is not being created;
  1639. //                an existing one is being reconstituted.
  1640. //
  1641. //                The part first checks to see if we can match its frame to an
  1642. //                ID in the Display frame list; if so, we put the frame into the
  1643. //                proxy. For frames we do not recognize, just add them.
  1644. //
  1645. // Warning:        This method may be called during editor swapping, with a frame
  1646. //                not recognized by the part. This is ok. Just treat the case as
  1647. //                if a "new" frame were being added to the part.
  1648. //------------------------------------------------------------------------------
  1649.  
  1650. void Cappuccino::DisplayFrameConnected( Environment*    ev,
  1651.                                         ODFrame*        frame )
  1652. {
  1653.     SOM_Trace("Cappuccino","DisplayFrameConnected");
  1654.  
  1655.     // Iterate over our display collection to match the frame with
  1656.     // an existing proxy with the correct frame ID. If we find it,
  1657.     // replace the ID with the actual frame. If we don't find it,
  1658.     // treat it as a newly "added" frame.
  1659.     ODBoolean found = kODFalse;
  1660.     CListIterator fiter(fDisplayFrames);
  1661.     for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
  1662.             fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() )
  1663.     {
  1664.         if ( proxy->GetID() == frame->GetID(ev) )
  1665.         {
  1666.             // The proxy class will refcount the frame passed to it, so we
  1667.             // don't need to worry about refcounting the display frame.
  1668.             proxy->SetFrame(ev, frame);
  1669.             found = kODTrue;
  1670.         }
  1671.     }
  1672.  
  1673.     // Parts typically operate under the assumption that they have previous
  1674.     // knowledge of a frame before it is connected to it. This knowledge
  1675.     // should come from having read in the frame reference when the part
  1676.     // was internalized. If the frame is an "unknown", the part was probably
  1677.     // bound to another editors storage unit because the editor is missing or
  1678.     // the user changed the editor in the Info dialog. 
  1679.     if ( found )
  1680.     {
  1681.         // If a display frame is connected to us with an unrecognizable
  1682.         // presentation, we need to set it to something meaningful.
  1683.     
  1684.         if ( frame->GetPresentation(ev) != gGlobals->fMainPresentation )
  1685.             frame->SetPresentation(ev, gGlobals->fMainPresentation);
  1686.         
  1687.         if ( frame->IsRoot(ev) )
  1688.         {
  1689.             // If the frame being added is a root frame, we know that a window
  1690.             // is associated with this frame. Notify ourselves that we need to 
  1691.             // clean it up when the frame goes away.
  1692.             CFrameInfo* frameInfo = CFrameInfo::GetFrameInfo(ev, frame);
  1693.             frameInfo->SetShouldDisposeWindow(kODTrue);
  1694.             
  1695.             // In addition, we need to verify that the frame is in "frame" view.
  1696.             // If the user dragged an icon from a document to Finder and then
  1697.             // opens the resultant document, the view would be "icon". However
  1698.             // displaying a icon is useless, so we need to change the view to
  1699.             // frame.
  1700.             if ( frame->GetViewType(ev) != gGlobals->fFrameView )
  1701.                 frame->SetViewType(ev, gGlobals->fFrameView);    
  1702.         }
  1703.  
  1704. #ifndef qViewerBuild
  1705.         // Since we support drag-and-drop, turn it on.
  1706.         frame->SetDroppable(ev, kODTrue);
  1707. #endif
  1708.     }
  1709.     else
  1710.     {
  1711.         // If an unrecognizable frame is connected to us, treat it like a "new"
  1712.         // frame and call our method to add it.
  1713.         this->DisplayFrameAdded(ev, frame);
  1714.     }
  1715. }
  1716.  
  1717. //------------------------------------------------------------------------------
  1718. // Method:        DisplayFrameRemoved
  1719. // Origin:        ODPart
  1720. //
  1721. // Description:    This method is called in response to a frame being removed from
  1722. //                the part.
  1723. //
  1724. //                The part removes the frame from its internal display frame list
  1725. //                and reliquishes any foci that it still owned. Lastly, if the
  1726. //                frame has a source frame (it was the root frame of a part
  1727. //                window), we will record the part window bounds so that any
  1728. //                subsequent part windows opened on the source frame will appear
  1729. //                in the same location.
  1730. //------------------------------------------------------------------------------
  1731.  
  1732. void Cappuccino::DisplayFrameRemoved( Environment*    ev,
  1733.                                       ODFrame*        frame )
  1734. {
  1735.     SOM_Trace("Cappuccino","DisplayFrameRemoved");
  1736.     
  1737.     ASSERT_NOT_NULL(frame);
  1738.  
  1739.     TRY
  1740.         CFrameInfo* frameInfo = CFrameInfo::GetFrameInfo(ev, frame);
  1741.     
  1742.         // Make sure the frame going away does not own any foci. Forgetting
  1743.         // to do this, will cause a "refcounting" error when the frame
  1744.         // is deleted by the draft.
  1745.         this->RelinquishAllFoci(ev, frame);
  1746.         
  1747.         // If removing a child window, show zoom rects back to source.
  1748.         // NOTE: This has to be done before CleanupDisplayFrame because 
  1749.         // CleanupDisplayFrame will remove the relationship.
  1750.         if ( frame->IsRoot(ev) && frameInfo->HasSourceFrame() )
  1751.         {
  1752.             TempODWindow window = frame->AcquireWindow(ev);
  1753.             this->ZoomPartWindow(ev, frameInfo->GetSourceFrame(ev), 
  1754.                                  window, kWindowClosing);
  1755.         }
  1756.                 
  1757.         // Clean up the display frame.
  1758.         this->CleanupDisplayFrame(ev, frame, kFrameRemoved);
  1759.         // Clean up any associated window.
  1760.         this->CleanupWindow(ev, frame);
  1761.         // Dispose of the frame's runtime state info.
  1762.         frame->SetPartInfo(ev, (ODInfoType) kODNULL);
  1763.         ODDeleteObject(frameInfo);
  1764.         
  1765.         // Remove the display frame from our collection.
  1766.         CListIterator fiter(fDisplayFrames);
  1767.         for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
  1768.                 fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() )
  1769.         {
  1770.             if ( ODObjectsAreEqual(ev, proxy->GetFrame(ev), frame) )
  1771.             {
  1772.                 // Delete the proxy object and its contents. The frame's
  1773.                 // refcount will be decremented in the proxy destructor.
  1774.                 fiter.RemoveCurrent();
  1775.                 delete proxy;
  1776.             }
  1777.         }
  1778.  
  1779.         // Since we maintain a persistent list of weak references to our
  1780.         // display frames, having one removed from the part dirties it.
  1781.         this->SetDirty(ev);
  1782.     
  1783.     CATCH_ALL
  1784.         // Alert the user of the problem.
  1785.         this->DoDialogBox(ev, frame, kErrorBoxID, kErrRemoveFrame);
  1786.         // Change the exception value, so the DocShell doesn't display an
  1787.         // error dialog.
  1788.         SetErrorCode(kODErrAlreadyNotified);
  1789.         // Alert the caller.
  1790.         RERAISE;
  1791.     ENDTRY
  1792. }
  1793.  
  1794. //------------------------------------------------------------------------------
  1795. // Method:        DisplayFrameClosed
  1796. // Origin:        ODPart
  1797. //
  1798. // Description:    This method is called in response to a frame being closed as a
  1799. //                result of the document having been closed by the user.
  1800. //
  1801. //                The part behaves much the same way that it would if a frame were
  1802. //                removed (see above), except that we don't need to cache runtime
  1803. //                information. 
  1804. //------------------------------------------------------------------------------
  1805.  
  1806. void Cappuccino::DisplayFrameClosed( Environment*    ev,
  1807.                                      ODFrame*        frame )
  1808. {
  1809.     SOM_Trace("Cappuccino","DisplayFrameClosed");
  1810.  
  1811.     ASSERT_NOT_NULL(frame);
  1812.  
  1813.     TRY
  1814.         CFrameInfo* frameInfo = CFrameInfo::GetFrameInfo(ev, frame);
  1815.     
  1816.         // Make sure the frame going away does not own any foci. Forgetting
  1817.         // to do this, will cause a "refcounting" error when the frame
  1818.         // is deleted by the draft.
  1819.         this->RelinquishAllFoci(ev, frame);
  1820.  
  1821.         // Clean up the display frame.
  1822.         this->CleanupDisplayFrame(ev, frame, kFrameClosed);
  1823.         // Clean up any associated window.
  1824.         this->CleanupWindow(ev, frame);
  1825.         // Dispose of the frame's runtime state info.
  1826.         frame->SetPartInfo(ev, (ODInfoType) kODNULL);
  1827.         ODDeleteObject(frameInfo);
  1828.         
  1829.         // Remove the display frame from our collection.
  1830.         CListIterator fiter(fDisplayFrames);
  1831.         for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
  1832.                 fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() )
  1833.         {
  1834.             if ( proxy->GetID() == frame->GetID(ev) )
  1835.             {
  1836.                 // Release the frame reference, but don't get rid of the
  1837.                 // proxy object because "closed" frames may be reconnected
  1838.                 // before the document is closed.
  1839.                 proxy->Purge(ev);
  1840.             }
  1841.         }
  1842.         
  1843.     CATCH_ALL
  1844.         // Alert the user of the problem.
  1845.         this->DoDialogBox(ev, frame, kErrorBoxID, kErrRemoveFrame);
  1846.         // Change the exception value, so the DocShell doesn't display an
  1847.         // error dialog.
  1848.         SetErrorCode(kODErrAlreadyNotified);
  1849.         // Alert the caller.
  1850.         RERAISE;
  1851.     ENDTRY
  1852. }
  1853.  
  1854. //------------------------------------------------------------------------------
  1855. // Method:        CleanupDisplayFrame
  1856. // Origin:        Cappuccino
  1857. //
  1858. // Description:    This method is called when a frame has been closed or removed.
  1859. //                The method cleans up the references and state information stored
  1860. //                in the CFrameInfo class.
  1861. //------------------------------------------------------------------------------
  1862.  
  1863. void Cappuccino::CleanupDisplayFrame(    Environment*    ev,
  1864.                                         ODFrame*        frame,
  1865.                                         ODBoolean        frameRemoved )
  1866. {
  1867.     SOM_Trace("Cappuccino","CleanupDisplayFrame");
  1868.  
  1869.     ASSERT_NOT_NULL(frame);
  1870.  
  1871.     ODError        error = noErr;
  1872.     CFrameInfo*    frameInfo = CFrameInfo::GetFrameInfo(ev, frame);
  1873.  
  1874.     TRY
  1875.         // If we are the root of a child window, we need to notify
  1876.         // our source frame that we are going away.
  1877.         if ( frameInfo->HasSourceFrame() )
  1878.         {
  1879.             ODFrame* sourceFrame = frameInfo->GetSourceFrame(ev);
  1880.             CFrameInfo* sourceFrameInfo = CFrameInfo::GetFrameInfo(ev, sourceFrame);
  1881.  
  1882.             if ( frameRemoved )
  1883.             {
  1884.                 // Invalidate the source frame. We do this because the
  1885.                 // source frame may have a unique display when it has
  1886.                 // been opened into a part window. This forces the
  1887.                 // frame to redraw "not opened".
  1888.  
  1889.                 // Here, we check to see if the source of the frame is frame
  1890.                 // view, in which case we don't invalidate it because our
  1891.                 // frame view doesn't draw any differently if there was a
  1892.                 // child window open.
  1893.                 if ( sourceFrame->GetViewType(ev) != gGlobals->fFrameView )
  1894.                     sourceFrame->Invalidate(ev, kODNULL, kODNULL);
  1895.             }
  1896.             
  1897.             // Tell the source frame that its dependent is going away.
  1898.             sourceFrameInfo->ReleaseDependentFrame(ev);            
  1899.  
  1900.             // Release our reference to the source frame.
  1901.             frameInfo->ReleaseSourceFrame(ev);
  1902.  
  1903.             // If the frame is the root, it is a part window going away
  1904.             // and we need to notify our source frame that it no longer
  1905.             // has a part window.
  1906.             if ( frame->IsRoot(ev) )
  1907.                 sourceFrameInfo->SetPartWindow(ev, kODNULL);
  1908.         }
  1909.     CATCH_ALL
  1910.         error = ErrorCode();
  1911.     ENDTRY
  1912.     
  1913.     TRY
  1914.         // If the frame was removed from the document, we need to remove
  1915.         // any child window displaying that frame.
  1916.         if ( frameRemoved )
  1917.         {
  1918.             // If we have a child window, we need to close it.
  1919.             ODWindow* window = frameInfo->AcquirePartWindow(ev);
  1920.  
  1921.             if ( window )
  1922.             {
  1923.                 frameInfo->SetPartWindow(ev, kODNULL);
  1924.                 window->CloseAndRemove(ev);
  1925.             }
  1926.         }
  1927.     CATCH_ALL
  1928.         error = ErrorCode();
  1929.     ENDTRY
  1930.  
  1931.     TRY
  1932.         // If we have dependent frames, we need to notify them that we
  1933.         // are going away.
  1934.     
  1935.         if ( frameInfo->HasDependentFrame() )
  1936.         {
  1937.             // Get the frame that is dependent on this one. We can safely
  1938.             // do this because we only reference our own display frames.
  1939.             ODFrame* dependentFrame = frameInfo->GetDependentFrame(ev);
  1940.             CFrameInfo* dependentFrameInfo = CFrameInfo::GetFrameInfo(ev, dependentFrame);
  1941.  
  1942.             // Tell the dependent frame that its source is going away.
  1943.             dependentFrameInfo->ReleaseSourceFrame(ev);
  1944.             
  1945.             // Release our reference to the dependent frame.
  1946.             frameInfo->ReleaseDependentFrame(ev);
  1947.         }
  1948.     CATCH_ALL
  1949.         error = ErrorCode();
  1950.     ENDTRY
  1951.     
  1952.     // If anything went wrong, signal an error.
  1953.     THROW_IF_ERROR(error);
  1954. }
  1955.  
  1956. //------------------------------------------------------------------------------
  1957. // Method:        AttachSourceFrame
  1958. // Origin:        ODPart
  1959. //
  1960. // Description:    If the part which we are contained in is opened into a part
  1961. //                window, it is required to iterate over its embedded frames and
  1962. //                add new display frames in the part window. After each new
  1963. //                embedded frame is created, this method will be called.
  1964. //
  1965. //                Given all that, and given our lack of interesting
  1966. //                content, we just validate the frame and attach it to its source.
  1967. //------------------------------------------------------------------------------
  1968.  
  1969. void Cappuccino::AttachSourceFrame( Environment*    ev,
  1970.                                     ODFrame*        frame,
  1971.                                     ODFrame*        sourceFrame )
  1972. {
  1973.     SOM_Trace("Cappuccino","AttachSourceFrame");
  1974.  
  1975.     ASSERT_NOT_NULL(frame);
  1976.  
  1977.     // Tell the new frame about its source.
  1978.     CFrameInfo* frameInfo = CFrameInfo::GetFrameInfo(ev, frame);
  1979.     frameInfo->SetSourceFrame(ev, sourceFrame);
  1980.     
  1981.     // And tell the source about its new dependent.
  1982.     frameInfo = CFrameInfo::GetFrameInfo(ev, sourceFrame);
  1983.     frameInfo->SetDependentFrame(ev, frame);
  1984.     
  1985.     // In both cases, refcounting of the frame and sourceFrame is
  1986.     // handled by the CFrameInfo class.
  1987. }
  1988.  
  1989. //------------------------------------------------------------------------------
  1990. // Method:        ViewTypeChanged
  1991. // Origin:        ODPart
  1992. //
  1993. // Description:    This method is called in response to one of our display frame's
  1994. //                viewType field being modified. We call this method on ourselves
  1995. //                when new display frames are added, but it call also be called
  1996. //                when the user changes the view in the "part info" dialog.
  1997. //
  1998. //                The part first loads the appropriate view icons if needed and
  1999. //                then calculates a new "used" shape based on the bounds of the
  2000. //                new view type. If any problems occur while changing the view,
  2001. //                the part defaults back to frame view (the part's default view).
  2002. //------------------------------------------------------------------------------
  2003.  
  2004. void Cappuccino::ViewTypeChanged( Environment*    ev,
  2005.                                   ODFrame*        frame )
  2006. {
  2007.     SOM_Trace("Cappuccino","ViewTypeChanged");
  2008.  
  2009.     // Change this frame's used shape to match the new view setting.
  2010.     TempODShape newUsedShape = this->CalcNewUsedShape(ev, frame);    
  2011.  
  2012.     frame->Invalidate(ev, kODNULL, kODNULL);
  2013.     frame->ChangeUsedShape(ev, newUsedShape, kODNULL);
  2014.     frame->Invalidate(ev, kODNULL, kODNULL);
  2015. }
  2016.  
  2017. //------------------------------------------------------------------------------
  2018. // Method:        PresentationChanged
  2019. // Origin:        ODPart
  2020. //
  2021. // Description:    This method is called when the presentation of a frame has been
  2022. //                changed.
  2023. //------------------------------------------------------------------------------
  2024.  
  2025. void Cappuccino::PresentationChanged( Environment*    ev,
  2026.                                       ODFrame*        frame )
  2027. {
  2028.     SOM_Trace("Cappuccino","PresentationChanged");
  2029.  
  2030. }
  2031.  
  2032. //------------------------------------------------------------------------------
  2033. // Method:        SequenceChanged
  2034. // Origin:        ODPart
  2035. //
  2036. // Description:    This method is called when a frame's place in a sequence has
  2037. //                been changed.
  2038. //------------------------------------------------------------------------------
  2039.  
  2040. void Cappuccino::SequenceChanged( Environment*    ev,
  2041.                                   ODFrame*        frame )
  2042. {
  2043.     SOM_Trace("Cappuccino","SequenceChanged");
  2044.  
  2045. }
  2046.  
  2047. //------------------------------------------------------------------------------
  2048. // Method:        ContainingPartPropertiesUpdated
  2049. // Origin:        ODPart
  2050. //
  2051. // Description:    This method is called when the containing part attempts to
  2052. //                change some properties of the embedded part.  We should examine
  2053. //                the properties of the storage unit for anything we understand.
  2054. //------------------------------------------------------------------------------
  2055.  
  2056. void Cappuccino::ContainingPartPropertiesUpdated( Environment*        ev,
  2057.                                                   ODFrame*            frame,
  2058.                                                   ODStorageUnit*    propertyUnit )
  2059. {
  2060.     SOM_Trace("Cappuccino","ContainingPartPropertiesUpdated");
  2061.  
  2062. }
  2063.  
  2064. //------------------------------------------------------------------------------
  2065. // Method:        CalcNewUsedShape
  2066. // Origin:        Cappuccino
  2067. //
  2068. // Description:    This method is called in response to one of display frame's view
  2069. //                being changed. The method calculates the appropriate usedShape
  2070. //                for the new view type.
  2071. //------------------------------------------------------------------------------
  2072.  
  2073. ODShape* Cappuccino::CalcNewUsedShape( Environment*        ev,
  2074.                                          ODFrame*            frame )
  2075. {
  2076.     SOM_Trace("Cappuccino","CalcNewUsedShape");
  2077.  
  2078.     ASSERT_NOT_NULL(frame);
  2079.  
  2080.     ODShape* usedShape = kODNULL;
  2081.     ODVolatile(usedShape);
  2082.     
  2083.     // If the view is "frame", we intentionally return a nil shape;
  2084.     // doing so, will reset the used shape to equal the frame shape.
  2085.  
  2086.     ODTypeToken view = frame->GetViewType(ev);
  2087.  
  2088.     if ( view == gGlobals->fLargeIconView ||
  2089.          view == gGlobals->fSmallIconView ||
  2090.          view == gGlobals->fThumbnailView )
  2091.     {
  2092.         RgnHandle usedRgn = ODNewRgn();
  2093.         TRY
  2094.             Rect bounds;
  2095.             if ( view == gGlobals->fLargeIconView || view == gGlobals->fSmallIconView )
  2096.             {
  2097.                 CUsingLibraryResources res;
  2098.  
  2099.                 // Set the bounds rect for the icon size.
  2100.                 SetRect(&bounds, 0, 0,
  2101.                         (view == gGlobals->fLargeIconView) ? kODLargeIconSize : kODSmallIconSize,
  2102.                         (view == gGlobals->fLargeIconView) ? kODLargeIconSize : kODSmallIconSize);
  2103.  
  2104.                 // Convert the icon mask into a Region.
  2105.                 THROW_IF_ERROR( IconIDToRgn(usedRgn, &bounds, atAbsoluteCenter, kBaseResourceID) );
  2106.             }
  2107.             else if ( view == gGlobals->fThumbnailView )
  2108.             {    
  2109.                 PicHandle thumbnail = this->GenerateThumbnail(ev, frame);
  2110.  
  2111.                 if ( thumbnail )
  2112.                     bounds = (**thumbnail).picFrame;
  2113.                 else
  2114.                     SetRect(&bounds, 0, 0, kODThumbnailSize, kODThumbnailSize);
  2115.                     
  2116.                 RectRgn(usedRgn,&bounds);
  2117.             }
  2118.         
  2119.             usedShape = frame->CreateShape(ev);
  2120.             usedShape->SetQDRegion(ev, usedRgn);
  2121.                             
  2122.         CATCH_ALL
  2123.             ODSafeReleaseObject(usedShape);
  2124.             ODDisposeHandle((ODHandle) usedRgn);
  2125.             usedShape = kODNULL;
  2126.         ENDTRY
  2127.     }
  2128.         
  2129.     return usedShape;
  2130. }
  2131.  
  2132. //------------------------------------------------------------------------------
  2133. // Method:        UpdateFrame
  2134. // Origin:        Cappuccino
  2135. //
  2136. // Description:    This method is called in response to one of our
  2137. //------------------------------------------------------------------------------
  2138.  
  2139. void Cappuccino::UpdateFrame( Environment*    ev,
  2140.                              ODFrame*        frame,
  2141.                              ODTypeToken    view,
  2142.                              ODShape*        usedShape )
  2143. {
  2144.     SOM_Trace("Cappuccino","UpdateFrame");
  2145.  
  2146.     TRY
  2147.         // Update the frame to have the new view and UsedShape.
  2148.         frame->Invalidate(ev, kODNULL, kODNULL);
  2149.         frame->SetViewType(ev, view);
  2150.         frame->ChangeUsedShape(ev, usedShape, kODNULL);
  2151.         frame->Invalidate(ev, kODNULL, kODNULL);
  2152.     CATCH_ALL
  2153.         // Failing isn't great, but we can live with it, so don't set ev.
  2154.     ENDTRY
  2155. }
  2156.  
  2157. //------------------------------------------------------------------------------
  2158. // Method:        GenerateThumbnail
  2159. // Origin:        Cappuccino
  2160. //
  2161. // Description:    This method is called by the part to generate a thumbnail view
  2162. //                from the current content.
  2163. //
  2164. //                The part has no content, so we merely load a picture.
  2165. //------------------------------------------------------------------------------
  2166.  
  2167. PicHandle Cappuccino::GenerateThumbnail( Environment*    ev,
  2168.                                          ODFrame*        frame )
  2169. {
  2170.     SOM_Trace("Cappuccino","GenerateThumbnail");
  2171.     
  2172.     if ( gGlobals->fThumbnail == kODNULL )
  2173.     {
  2174.         // In cases where a part has been instantiated from scratch and has no
  2175.         // content (yet), it is appropriate to display a PICT or some graphic
  2176.         // in place of a "real" thumbnail.
  2177.         
  2178.         LoadThumbnail(ev, &gGlobals->fThumbnail);
  2179.     
  2180.         // If we were unable to load the PICT resource for whatever reason
  2181.         // we will default back to a "frame" view and throw the Resource
  2182.         // Manager error as an exception.
  2183.         if ( gGlobals->fThumbnail == kODNULL )
  2184.         {
  2185.             frame->SetViewType(ev, gGlobals->fFrameView);
  2186.             
  2187.             // There is a bug in ResError, when resources are not found,
  2188.             // which may cause noErr to be returned. If that is the case,
  2189.             // we throw resNotFound.
  2190.             THROW_IF_ERROR((ODError) ResError());
  2191.             THROW(resNotFound);
  2192.         }
  2193.     }
  2194.             
  2195.     return (PicHandle) gGlobals->fThumbnail;
  2196. }
  2197.  
  2198. //------------------------------------------------------------------------------
  2199. // Method:        FrameShapeChanged
  2200. // Origin:        ODPart
  2201. //
  2202. // Description:    This method is called in response to a frame's shape being
  2203. //                altered, either by the user or the part we are embedded in.
  2204. //------------------------------------------------------------------------------
  2205.  
  2206. void Cappuccino::FrameShapeChanged( Environment*    ev,
  2207.                                     ODFrame*        frame )
  2208. {
  2209.     SOM_Trace("Cappuccino","FrameShapeChanged");
  2210.  
  2211.     // Adjust the "used" shape for the new frame shape.
  2212.     TempODShape usedShape = this->CalcNewUsedShape(ev, frame);
  2213.     frame->ChangeUsedShape(ev, usedShape, kODNULL);
  2214. }
  2215.  
  2216. //------------------------------------------------------------------------------
  2217. // Method:        Open
  2218. // Origin:        ODPart
  2219. //
  2220. // Description:    This method is called when OpenDoc, a containing part, or the
  2221. //                active editor would like to open a frame into a seperate window.
  2222. //                If a source frame is passed into this method, the editor is
  2223. //                being asked one of two things. If the frame is the root, we are
  2224. //                being asked to open an existing document. If the frame is not
  2225. //                the root, we are being asked to open a part window. If a source
  2226. //                frame is not specified, the editor is being asked to open a new
  2227. //                window.
  2228. //------------------------------------------------------------------------------
  2229.  
  2230. ODID Cappuccino::Open( Environment*    ev, ODFrame* frame )
  2231. {
  2232.     SOM_Trace("Cappuccino","Open");
  2233.  
  2234.     ODID windowID;
  2235.     TempODWindow window(kODNULL);
  2236.  
  2237.     WindowProperties* windowProperties = kODNULL;
  2238.     ODVolatile(windowProperties);
  2239.  
  2240.     TRY
  2241.         // Because the frame parameter being passed to us can be one of
  2242.         // three things, we must determine what it is; either the root
  2243.         // frame of a existing document, the source frame for a part
  2244.         // window, or null if we are opening a new document.
  2245.     
  2246.         if ( frame == kODNULL )
  2247.         {
  2248.             // Calculate the bounding rectangle for a new window
  2249.             Rect windowRect = this->CalcPartWindowSize(ev, kODNULL);
  2250.             // Get the default setting for a document window.
  2251.             windowProperties = this->GetDefaultWindowProperties(ev, kODNULL, &windowRect);
  2252.             // Create a Mac Window and register it with OpenDoc.
  2253.             window = this->CreateWindow(ev, kODNULL, kODFrameObject, windowProperties);
  2254.         }
  2255.         else if ( frame->IsRoot(ev) )
  2256.         {
  2257.             // Get the previously saved settings for the document window.
  2258.             windowProperties = this->GetSavedWindowProperties(ev, frame);
  2259.             
  2260.             if ( windowProperties == kODNULL )
  2261.             {
  2262.                 // Calculate the bounding rectangle for a new window
  2263.                 Rect windowRect = this->CalcPartWindowSize(ev, frame);
  2264.                 // Get the default setting for a document window.
  2265.                 windowProperties = this->GetDefaultWindowProperties(ev, kODNULL, &windowRect);
  2266.             }
  2267.  
  2268.             // Create a Mac Window and register it with OpenDoc.
  2269.             window = this->CreateWindow(ev, frame, kODFrameObject, windowProperties);
  2270.             
  2271.             // We release the source frame here because we didn't call
  2272.             // EndGetWindowProperties and becuase we are done with it.
  2273.             ODReleaseObject(ev, windowProperties->sourceFrame);
  2274.         }
  2275.         else // frame is a source frame
  2276.         {
  2277.             window = this->AcquireFramesWindow(ev, frame);
  2278.     
  2279.             if ( window == kODNULL )
  2280.             {
  2281.                 // Calculate the bounding rectangle for a new window
  2282.                 Rect windowRect = this->CalcPartWindowSize(ev, frame);
  2283.                 // Get the default setting for a document window.
  2284.                 windowProperties = this->GetDefaultWindowProperties(ev, frame, &windowRect);
  2285.                 // Create a Mac Window and register it with OpenDoc.
  2286.                 window = this->CreateWindow(ev, kODNULL, kODFrameObject, windowProperties);
  2287.                 
  2288.                 // Tell the source frame that it is opened in a part window.
  2289.                 CFrameInfo* frameInfo = CFrameInfo::GetFrameInfo(ev, frame);
  2290.                 frameInfo->SetPartWindow(ev, window);
  2291.  
  2292.                 this->ZoomPartWindow(ev, frame, window, kWindowOpening);
  2293.             }
  2294.         }
  2295.     
  2296.         // Create the window's root facet.
  2297.         window->Open(ev);
  2298.         // Make the window visible.
  2299.         window->Show(ev);
  2300.         // Activate and select the window.
  2301.         window->Select(ev);
  2302.     
  2303.         // Cleanup allocate memory.
  2304.         ODDeleteObject(windowProperties);
  2305.         
  2306.         // Get window id to return.
  2307.         windowID = (window ? window->GetID(ev) : kODNULLID);
  2308.     
  2309.     CATCH_ALL
  2310.         // If we threw early, the source frame's refcount may be too high.
  2311.         if ( windowProperties )
  2312.             ODSafeReleaseObject(windowProperties->sourceFrame);
  2313.         // Cleanup the created items.
  2314.         ODDeleteObject(windowProperties);
  2315.         windowID = kODNULLID;
  2316.         // Alert the caller.
  2317.         RERAISE;
  2318.     ENDTRY
  2319.  
  2320.     return windowID;
  2321. }
  2322.  
  2323. //------------------------------------------------------------------------------
  2324. // Method:        CreateFrameInfo
  2325. // Origin:        Cappuccino
  2326. //
  2327. // Description:    This method is called by the part when a CFrameInfo object
  2328. //                needs to be created for a frame.                
  2329. //------------------------------------------------------------------------------
  2330.  
  2331. CFrameInfo* Cappuccino::CreateFrameInfo( Environment*        ev,
  2332.                                             ODFrame*            frame )
  2333. {
  2334.     return new CFrameInfo(fSession);
  2335. }
  2336.  
  2337. //------------------------------------------------------------------------------
  2338. // Method:        ZoomPartWindow
  2339. // Origin:        Cappuccino
  2340. //
  2341. // Description:    This method is called by the part when a frame is being opened
  2342. //                or closed in the case that zooming rectangles should be shown.                
  2343. //------------------------------------------------------------------------------
  2344.  
  2345. void Cappuccino::ZoomPartWindow( Environment*        ev,
  2346.                                     ODFrame*            frame,
  2347.                                     ODWindow*            window,
  2348.                                     ODBoolean            isZoomingOpen )
  2349. {
  2350.     ASSERT_NOT_NULL(frame);
  2351.     ASSERT_NOT_NULL(window);
  2352.     
  2353.     const ODSShort kNumZoomSteps = 12;
  2354.  
  2355.     Rect frameRect;
  2356.     {
  2357.         // We need to know which facet of the frame we are opening to position
  2358.         // the child window.
  2359.         ODFacet* zoomFacet = kODNULL;
  2360.         
  2361.         TRY
  2362.             zoomFacet = this->GetActiveFacetForFrame(ev, frame);
  2363.         CATCH_ALL
  2364.         ENDTRY
  2365.         
  2366.         // In case there isn't an active facet for the frame, .
  2367.         if ( zoomFacet == kODNULL )
  2368.         {
  2369.             TempODFrameFacetIterator iter(ev, frame);
  2370.             zoomFacet = iter.First();
  2371.         }
  2372.         
  2373.         if ( zoomFacet != kODNULL )
  2374.         {
  2375.             // For doing the zoom rects, we need the to know the area of the
  2376.             // document the frame occupies. We do this by getting the bouding
  2377.             // box and offsetting it by the aggregate external window transform
  2378.             // of the facet.
  2379.             TempODTransform windowFrameTransform = zoomFacet->AcquireWindowFrameTransform(ev, kODNULL);
  2380.             TempODShape boundsShape = ODCopyAndRelease(ev, zoomFacet->GetFrame(ev)
  2381.                                                             ->AcquireFrameShape(ev, kODNULL));
  2382.             
  2383.             // Translate the bounds rect into window coordinates.
  2384.             boundsShape->Transform(ev, windowFrameTransform);
  2385.             
  2386.             // Get and convert the bounding box into a QuickDraw rectangle.
  2387.             ODRect bbox;
  2388.             boundsShape->GetBoundingBox(ev, &bbox);
  2389.             FixedToIntRect(bbox, frameRect);
  2390.                 
  2391.             // Set the port and origin so we can convert the rect to
  2392.             // global Window Mgr coordinates.
  2393.             SetPort(zoomFacet->GetCanvas(ev)->GetQDPort(ev));
  2394.             SetOrigin(0, 0);
  2395.             
  2396.             // Convert the local coordinates to global Window Mgr coordinates.
  2397.             LocalToGlobal((Point*) &frameRect.top);
  2398.             LocalToGlobal((Point*) &frameRect.bottom);
  2399.         }
  2400.     }
  2401.     
  2402.     Rect windowRect;
  2403.     {
  2404.         ODPlatformWindow platformWindow = window->GetPlatformWindow(ev);
  2405.  
  2406.         windowRect = platformWindow->portRect;
  2407.         windowRect.top -= kMacWindowTitleBarHeight;
  2408.         
  2409.         // Set the port and origin so we can convert the rect to
  2410.         // global Window Mgr coordinates.
  2411.         SetPort(platformWindow);
  2412.         SetOrigin(0, 0);
  2413.         
  2414.         // Convert the local coordinates to global Window Mgr coordinates.
  2415.         LocalToGlobal((Point*) &windowRect.top);
  2416.         LocalToGlobal((Point*) &windowRect.bottom);
  2417.     }
  2418.     
  2419.     Rect fromRect = isZoomingOpen ? frameRect  : windowRect;
  2420.     Rect toRect   = isZoomingOpen ? windowRect : frameRect;
  2421.     
  2422.     if ( !isZoomingOpen )
  2423.         window->Hide(ev);
  2424.  
  2425.     (void) ZoomRects(&fromRect, &toRect, kNumZoomSteps, 
  2426.                      isZoomingOpen ? zoomAccelerate : zoomDecelerate);
  2427. }
  2428.  
  2429. //------------------------------------------------------------------------------
  2430. // Method:        AcquireFramesWindow
  2431. // Origin:        Cappuccino
  2432. //
  2433. // Description:    This method is called by the part when a frame, that has been
  2434. //                previously opened, is being opened again.
  2435. //
  2436. //                The method retrieves the existing window for the frame and
  2437. //                returns it.                
  2438. //------------------------------------------------------------------------------
  2439.  
  2440. ODWindow* Cappuccino::AcquireFramesWindow(    Environment*    ev,
  2441.                                                ODFrame*        frame )
  2442. {
  2443.     SOM_Trace("Cappuccino","GetFramesWindow");
  2444.  
  2445.     ASSERT_NOT_NULL(frame);
  2446.     
  2447.     CFrameInfo* frameInfo = CFrameInfo::GetFrameInfo(ev, frame);
  2448.     return frameInfo->AcquirePartWindow(ev);
  2449. }
  2450.     
  2451. //------------------------------------------------------------------------------
  2452. // Method:        CreateWindow
  2453. // Origin:        Cappuccino
  2454. //
  2455. // Description:    This method is called by the part when a window needs to be
  2456. //                created for a frame being opened.
  2457. //
  2458. //                The part uses the information passed in windowProperties to 
  2459. //                create the appropriate window. The generated window is
  2460. //                registered with OpenDoc as a new window (RegisterWindow) or as a
  2461. //                window from an existing document (RegisterWindowForFrame).
  2462. //------------------------------------------------------------------------------
  2463.  
  2464. ODWindow* Cappuccino::CreateWindow( Environment*         ev,
  2465.                                     ODFrame*            frame,
  2466.                                     ODType                frameType,
  2467.                                     WindowProperties*    windowProperties)
  2468. {
  2469.     SOM_Trace("Cappuccino","CreateWindow");
  2470.  
  2471.     ODPlatformWindow    platformWindow    = kODNULL;
  2472.     ODWindow*            window            = kODNULL;
  2473.     
  2474.     // Using the name and the calculated rectangle, create a new window.
  2475.     // Note that we are allocating the window record in temp mem using
  2476.     // the OpenDoc memory mgr. This helps reduce app heap usage.
  2477.     // In addition, OpenDoc requires that all new windows be initially hidden
  2478.     // so that it can correctly layer windows/palettes.
  2479.     platformWindow = NewCWindow((Ptr)ODNewPtr(sizeof(WindowRecord)),
  2480.                                 &(windowProperties->boundsRect),
  2481.                                 windowProperties->title,
  2482.                                 kODFalse,                             // visible
  2483.                                 windowProperties->procID,
  2484.                                 (WindowPtr)-1L,
  2485.                                 windowProperties->hasCloseBox,
  2486.                                 windowProperties->refCon);
  2487.  
  2488.     if ( platformWindow )
  2489.     {
  2490.         TRY
  2491.             ODWindowState* windowState = fSession->GetWindowState(ev);
  2492.             
  2493.             // Shoud the window be saved in the document? Yes if the root frame is
  2494.             // persistent.
  2495.             ODBoolean saveWindow = ODISOStrEqual(frameType, kODFrameObject);
  2496.             
  2497.             // Tell the window object that we will be disposing the window record
  2498.             // when the root frame is closed/removed.
  2499.             ODBoolean shouldDispose = kODFalse;
  2500.                                 
  2501.             // Determine whether we are creating a new window (frame is null),
  2502.             // or opening a previous saved window (frame is valid).
  2503.             
  2504.             if ( frame == kODNULL )
  2505.             {                                
  2506.                 // Tell OpenDoc about it by creating an OpenDoc window object.
  2507.                 window = windowState->
  2508.                             RegisterWindow(ev, 
  2509.                                 platformWindow,                    // Macintosh WindowPtr
  2510.                                 frameType,                        // Frame type (Persistent/Non-persistent)
  2511.                                 windowProperties->isRootWindow,    // Is this a document window?
  2512.                                 windowProperties->isResizable,    // Is this window resizeable?
  2513.                                 windowProperties->isFloating,    // Is this window floating?
  2514.                                 saveWindow,                        // Should this window be persistent?
  2515.                                 shouldDispose,                    // (see comment above)
  2516.                                 fSelf,                            // Part reference to us
  2517.                                 gGlobals->fFrameView,            // What view should the window have?
  2518.                                 gGlobals->fMainPresentation,    // What presentation should the window have?
  2519.                                 windowProperties->sourceFrame);    // The display frame being opened, if any
  2520.             }
  2521.             else
  2522.             {
  2523.                 // Tell OpenDoc about it by creating an OpenDoc window object.
  2524.                 window = windowState->
  2525.                             RegisterWindowForFrame(ev, 
  2526.                                 platformWindow,                    // Macintosh WindowPtr
  2527.                                 frame,                             // Frame type (Persistent/Non-persistent)
  2528.                                 windowProperties->isRootWindow,    // Is this a document window?
  2529.                                 windowProperties->isResizable,    // Is this window resizeable?
  2530.                                 windowProperties->isFloating,    // Is this window floating?
  2531.                                 saveWindow,                        // Should this window be persistent?
  2532.                                 shouldDispose,                    // (see comment above)
  2533.                                 windowProperties->sourceFrame);    // The display frame being opened, if any
  2534.             }
  2535.             
  2536.         CATCH_ALL
  2537.             // Cleanup Macintosh Window.
  2538.             CloseWindow(platformWindow);
  2539.             ODDisposePtr(platformWindow);
  2540.             // Get the right error message for the problem.
  2541.             ODSShort errMsgNum = (!frame && windowProperties->sourceFrame)
  2542.                                     ? kErrCantOpenPartWindow : kErrCantOpenDocWindow;
  2543.             // Alert the user of the problem.
  2544.             this->DoDialogBox(ev, frame, kErrorBoxID, errMsgNum);
  2545.             // Change the exception value, so the DocShell doesn't display an
  2546.             // error dialog.
  2547.             SetErrorCode(kODErrAlreadyNotified);
  2548.             // Alert the caller.
  2549.             RERAISE;
  2550.         ENDTRY
  2551.     }
  2552.  
  2553.     return window;
  2554. }
  2555.     
  2556. //------------------------------------------------------------------------------
  2557. // Method:        CleanupWindow
  2558. // Origin:        Cappuccino
  2559. //
  2560. // Description:    This method is called by the part when a window needs to be
  2561. //                cleaned up for a frame being closed/removed.
  2562. //
  2563. //                The part deallocates the window buffer allocated in the
  2564. //                CreateWindow() method.
  2565. //------------------------------------------------------------------------------
  2566.  
  2567. void Cappuccino::CleanupWindow( Environment*     ev,
  2568.                                 ODFrame*        frame )
  2569. {
  2570.     SOM_Trace("Cappuccino","CleanupWindow");
  2571.     
  2572.     ASSERT_NOT_NULL(frame);
  2573.  
  2574.        TRY
  2575.         CFrameInfo*    frameInfo = CFrameInfo::GetFrameInfo(ev, frame);
  2576.         if ( frameInfo->ShouldDisposeWindow() )
  2577.         {
  2578.             TempODWindow window = frame->AcquireWindow(ev);
  2579.             THROW_IF_NULL(window);
  2580.             
  2581.             ODPlatformWindow windowPtr = window->GetPlatformWindow(ev);
  2582.             CloseWindow(windowPtr);
  2583.             ODDisposePtr(windowPtr);
  2584.         }
  2585.     CATCH_ALL
  2586.         this->DoDialogBox(ev, frame, kErrorBoxID, kErrWindowGone);
  2587.         // consume excpetion because it's not fatal.
  2588.     ENDTRY
  2589. }
  2590.  
  2591. //------------------------------------------------------------------------------
  2592. // Method:        GetDefaultWindowProperties
  2593. // Origin:        Cappuccino
  2594. //
  2595. // Description:    This method is called by the part when a new window is being
  2596. //                created. The method examines the frame which is being opened
  2597. //                a generates the default window parameters to pass to the
  2598. //                Mac Toolbox.
  2599. //------------------------------------------------------------------------------
  2600.  
  2601. WindowProperties*
  2602. Cappuccino::GetDefaultWindowProperties( Environment*     ev,
  2603.                                         ODFrame*        sourceFrame,
  2604.                                         Rect*            windowRect )
  2605. {
  2606.     SOM_Trace("Cappuccino","GetDefaultWindowProperties");
  2607.     
  2608.     WindowProperties* windowProperties = new WindowProperties;
  2609.  
  2610.     TRY
  2611.         // Calculate the offset for the window based on the sourceFrame.    
  2612.         if ( sourceFrame )
  2613.             this->CalcPartWindowPosition(ev, sourceFrame, windowRect);
  2614.         else
  2615.             OffsetRect(windowRect, kALittleNudge,
  2616.                         GetMBarHeight() + kMacWindowTitleBarHeight);    
  2617.     
  2618.         // Set the window bounds based on the calculated rect.
  2619.         windowProperties->boundsRect = *windowRect;
  2620.     
  2621.         // Get the part's name to use for the new window.
  2622.         TempODIText windowName = GetPartName(ev, fSelf, kCappuccinoCategory);
  2623.         // Convert the ODIText into a Pascal string.
  2624.         GetITextString(windowName, windowProperties->title);
  2625.         
  2626.         // Fill in the other fields of the Window Properties struct.
  2627.         
  2628.         windowProperties->procID = zoomDocProc;
  2629.         windowProperties->hasCloseBox = kODTrue;
  2630.         windowProperties->refCon = (long) kODNULL;
  2631.         windowProperties->wasVisible = kODFalse;
  2632.         windowProperties->isResizable = kODTrue;
  2633.         windowProperties->isFloating = kODFalse;
  2634.         windowProperties->isRootWindow = sourceFrame ? kODFalse : kODTrue;
  2635.         windowProperties->shouldShowLinks = kODFalse;
  2636.         windowProperties->sourceFrame = sourceFrame;
  2637.     CATCH_ALL
  2638.         // Clean up and...
  2639.         ODDeleteObject(windowProperties);
  2640.         // Alert the caller.
  2641.         RERAISE;
  2642.     ENDTRY
  2643.     
  2644.     return windowProperties;
  2645. }
  2646.  
  2647. //------------------------------------------------------------------------------
  2648. // Method:        GetSavedWindowProperties
  2649. // Origin:        Cappuccino
  2650. //
  2651. // Description:    This method is called by the part to read in saved information
  2652. //                for a window from an existing document.
  2653. //------------------------------------------------------------------------------
  2654.  
  2655. WindowProperties* Cappuccino::GetSavedWindowProperties( Environment*     ev,
  2656.                                                           ODFrame*        frame )
  2657. {
  2658.     SOM_Trace("Cappuccino","GetSavedWindowProperties");
  2659.  
  2660.     WindowProperties* windowProperties = new WindowProperties;
  2661.     
  2662.     // If we fail to load the window properties from storage, delete
  2663.     // the structure so the calling code will behave appropriately.    
  2664.     if ( BeginGetWindowProperties(ev, frame, windowProperties) )
  2665.     {    
  2666.         // Note: We don't call EndGetWindowProperties because it releases the
  2667.         // source frame, which we will need after this method returns.
  2668.         
  2669.         // Get the part's name to use for the new window.
  2670.         TempODIText windowName = GetPartName(ev, fSelf, kCappuccinoCategory);
  2671.         // Convert the ODIText into a Pascal string.
  2672.         GetITextString(windowName, windowProperties->title);
  2673.     
  2674.         // Verify the window is still visible on a monitor.
  2675.         
  2676.         RgnHandle windowRgn = ODNewRgn();
  2677.         ODBoolean repositionWindow = kODFalse;
  2678.         
  2679.         // We are only concerned with the window's title bar being
  2680.         // visible, so calcuate the titlebar rect from the current
  2681.         // window bounds.
  2682.         Rect adjustedBounds = windowProperties->boundsRect;
  2683.         adjustedBounds.bottom = adjustedBounds.top;
  2684.         adjustedBounds.top -= kMacWindowTitleBarHeight;
  2685.         
  2686.         // Intersect the monitor's region
  2687.         RectRgn(windowRgn, &adjustedBounds);
  2688.         SectRgn(windowRgn, GetGrayRgn(), windowRgn);
  2689.         
  2690.         if ( !EmptyRgn(windowRgn) )
  2691.         {
  2692.             // If the visible portion of the window is too small, we need
  2693.             // to reposition it.
  2694.             Rect intersectedBounds = (**windowRgn).rgnBBox;
  2695.             if ( (intersectedBounds.right-intersectedBounds.left < kMinHorzVisPortion) ||
  2696.                     (intersectedBounds.bottom-intersectedBounds.top < kMinVertVisPortion) )
  2697.                 repositionWindow = kODTrue;
  2698.         }
  2699.         else
  2700.         {
  2701.             // If the window is completely offscreen, we need to reposition it.
  2702.             repositionWindow = kODTrue;
  2703.         }
  2704.         ODDisposeHandle((ODHandle)windowRgn);
  2705.         
  2706.         // If not, we need to move it so the user can see it.
  2707.         if ( repositionWindow )
  2708.         {
  2709.             Rect windowRect = (windowProperties->boundsRect);
  2710.             // Move the window to {0,0} coordinates.
  2711.             OffsetRect(&windowRect, -windowRect.left, -windowRect.top);
  2712.             // Now move the window to the default window position.
  2713.             OffsetRect(&windowRect, kALittleNudge, GetMBarHeight() + kMacWindowTitleBarHeight);
  2714.             // Save the new window position in our windowProperties.
  2715.             windowProperties->boundsRect = windowRect;
  2716.         }
  2717.     }
  2718.     else
  2719.     {
  2720.         // If we were unable to re-load window properties, dispose of the
  2721.         // struct.
  2722.         ODDeleteObject(windowProperties);
  2723.     }
  2724.         
  2725.     return windowProperties;
  2726. }
  2727.  
  2728. //------------------------------------------------------------------------------
  2729. // Method:        CalcPartWindowSize
  2730. // Origin:        Cappuccino
  2731. //
  2732. // Description:    This method is called by the part to determine what size a new
  2733. //                window shoud be.
  2734. //------------------------------------------------------------------------------
  2735.  
  2736. Rect Cappuccino::CalcPartWindowSize( Environment*    ev,
  2737.                                      ODFrame*        sourceFrame )
  2738. {
  2739.     SOM_Trace("Cappuccino","CalcPartWindowSize");
  2740.  
  2741.     const ODSShort kOnePageWidth = 600;
  2742.     
  2743.     Rect    windowRect;
  2744.     ODRect    frameRect;
  2745.     
  2746.     // If a source frame is given, the part is being asked to open one of
  2747.     // its display frames into a part window. Otherwise, we are being opened
  2748.     // as the root frame of the current document and should size the window
  2749.     // accordingly.
  2750.  
  2751.     // Set up the child window's size to be that of the display frame being opened.
  2752.     if ( sourceFrame )
  2753.     {
  2754.         // Retrieve the fixed point bounding box for the frame.
  2755.         TempODShape frameShape = sourceFrame->AcquireFrameShape(ev, kODNULL);
  2756.         frameShape->GetBoundingBox(ev, &frameRect);
  2757.         
  2758.         // Convert that into a Quickdraw rectangle.
  2759.         FixedToIntRect(frameRect, windowRect);
  2760.     }
  2761.     // Otherwise, just open a large window.
  2762.     else
  2763.     {
  2764.         // (3 * kODLargeIconSize) prevents the window from covering the volume
  2765.         // icons on the desktop which is a violation of Macintosh HI Guidelines.
  2766.         
  2767.         SetRect(&windowRect, 0, 0,
  2768.                   ODQDGlobals.screenBits.bounds.right - (3 * kODLargeIconSize),
  2769.                   ODQDGlobals.screenBits.bounds.bottom
  2770.                       - GetMBarHeight() - kMacWindowTitleBarHeight - kALittleNudge);        
  2771.         
  2772.         if ( windowRect.right - windowRect.left > kOnePageWidth )
  2773.             windowRect.right = windowRect.left + kOnePageWidth;
  2774.     }
  2775.     
  2776.     return windowRect;
  2777. }
  2778.  
  2779. //------------------------------------------------------------------------------
  2780. // Method:        CalcPartWindowPosition
  2781. // Origin:        Cappuccino
  2782. //
  2783. // Description:    This method is called by the part to determine where to align
  2784. //                the new window (top left corner of the screen or tiled to a
  2785. //                frame).
  2786. //------------------------------------------------------------------------------
  2787.  
  2788. Rect Cappuccino::CalcPartWindowPosition( Environment*    ev,
  2789.                                          ODFrame*        frame,
  2790.                                          Rect*            partWindowBounds )
  2791. {
  2792.     SOM_Trace("Cappuccino","CalcPartWindowPosition");
  2793.  
  2794.     // We need to know which facet of the frame we are opening to position
  2795.     // the child window.
  2796.     ODFacet* activeFacet = this->GetActiveFacetForFrame(ev, frame);
  2797.     
  2798.     // This should never occur, but if it did, it would be fatal.
  2799.     // So we will just pass back the same rectangle.
  2800.     if ( activeFacet == kODNULL )
  2801.         return *partWindowBounds;
  2802.     
  2803.     // For the purposes of tiling, we need the to know the area of the
  2804.     // document the frame occupies. We do this by getting the bouding
  2805.     // box and offsetting it by the aggregate external window transform
  2806.     // of the facet.
  2807.     
  2808.     ODShape* frameShape = activeFacet->GetFrame(ev)->AcquireFrameShape(ev, kODNULL);
  2809.     TempODTransform windowFrameTransform = activeFacet->AcquireWindowFrameTransform(ev, kODNULL);
  2810.     TempODShape boundsShape = ODCopyAndRelease(ev, frameShape);
  2811.  
  2812.     // Translate the bounds rect into window coordinates.
  2813.     boundsShape->Transform(ev, windowFrameTransform);
  2814.     
  2815.     // Get and convert the bounding box into a QuickDraw rectangle.
  2816.     ODRect    bbox;
  2817.     Rect    bounds;
  2818.     boundsShape->GetBoundingBox(ev, &bbox);
  2819.     FixedToIntRect(bbox, bounds);
  2820.         
  2821.     // We then call our method to tile the child window.
  2822.     *partWindowBounds = TilePartWindow(ev, &bounds, partWindowBounds);
  2823.     
  2824.     // Set the port and origin so we can convert the rect to
  2825.     // global Window Mgr coordinates.
  2826.     SetPort(activeFacet->GetCanvas(ev)->GetQDPort(ev));
  2827.     SetOrigin(0,-kMacWindowTitleBarHeight);
  2828.     
  2829.     // Convert the local coordinates to global Window Mgr coordinates.
  2830.     LocalToGlobal((Point*)(&(partWindowBounds->top)));
  2831.     LocalToGlobal((Point*)(&(partWindowBounds->bottom)));
  2832.     
  2833.     return *partWindowBounds;
  2834. }
  2835.  
  2836. //------------------------------------------------------------------------------
  2837. // Method:        GetActiveFacetForFrame
  2838. // Origin:        Cappuccino
  2839. //
  2840. // Description:    This method is called by the part when it needs to know what the
  2841. //                current active facet is.
  2842. //
  2843. //                The part uses this method specifically to find the facet of a
  2844. //                source frame when opening a part window.
  2845. //------------------------------------------------------------------------------
  2846.  
  2847. ODFacet* Cappuccino::GetActiveFacetForFrame( Environment*    ev,
  2848.                                              ODFrame*        frame )
  2849. {
  2850.     SOM_Trace("Cappuccino","GetActiveFacetForFrame");
  2851.  
  2852.     ASSERT_NOT_NULL(frame);
  2853.  
  2854.     ODFacet*    facet = kODNULL;
  2855.     CFrameInfo*    frameInfo = CFrameInfo::GetFrameInfo(ev, frame);
  2856.     
  2857.     // If the frame is active, and it should be, get the active facet
  2858.     // from the frame state info.
  2859.     if ( frameInfo->IsFrameActive() )
  2860.     {
  2861.         facet = frameInfo->GetActiveFacet();
  2862.     }
  2863.     else
  2864.     // Otherwise, iterate over the display frames looking for one
  2865.     // that has an active facet... there should be at least one.
  2866.     {
  2867.         TempODFrameFacetIterator fiter(ev, frame);
  2868.         for ( ODFacet* selectedFacet = fiter.First(); fiter.IsNotComplete();
  2869.               selectedFacet = fiter.Next() )
  2870.         {
  2871.             if ( selectedFacet->IsSelected(ev) )
  2872.             {
  2873.                 facet = selectedFacet;
  2874.                 break;
  2875.             }
  2876.         }
  2877.     }
  2878.     
  2879.     // If there are no active facets anywhere, this method should never
  2880.     // have been called, so signal an error.
  2881.     if ( facet == kODNULL )
  2882.         THROW(kODErrInvalidFrame);
  2883.  
  2884.     return facet;
  2885. }
  2886.  
  2887. //------------------------------------------------------------------------------
  2888. // Method:        ContentUpdated
  2889. // Origin:        Cappuccino
  2890. //
  2891. // Description:    This method is called when the content has changed in order
  2892. //                to cause all of the frames belonging to this part to be told
  2893. //                that the content was updated.
  2894. //------------------------------------------------------------------------------
  2895.  
  2896. void Cappuccino::ContentUpdated( Environment*    ev )
  2897. {
  2898.     SOM_Trace("Cappuccino","ContentUpdated");
  2899.  
  2900.     ODUpdateID pasteUpdateID = fSession->UniqueUpdateID(ev);
  2901.  
  2902.     // Iterate over the frames we are displayed through and determine which
  2903.     // ones we need to invalidate.
  2904.     CListIterator fiter(fDisplayFrames);
  2905.     for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
  2906.             fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() )
  2907.     {
  2908.         // If the display frame is real (has been "connected" or was "added")
  2909.         // call ContentUpdated for the frame; otherwise, ignore it.
  2910.         if ( proxy->FrameIsLoaded(ev) )
  2911.         {
  2912.             proxy->GetFrame(ev)->ContentUpdated(ev, pasteUpdateID);
  2913.         }
  2914.     }
  2915. }
  2916.  
  2917. //------------------------------------------------------------------------------
  2918. // Method:        TryToEdit
  2919. // Origin:        Cappuccino
  2920. //
  2921. // Description:    This method is called when the content has changed in order
  2922. //                to cause all of the frames belonging to this part to be told
  2923. //                that the content was updated.
  2924. //------------------------------------------------------------------------------
  2925.  
  2926. ODBoolean Cappuccino::TryToEdit( Environment*        ev, 
  2927.                                  ODFrame*            frame )
  2928. {
  2929.     SOM_Trace("Cappuccino","CanEdit");
  2930.  
  2931.     ASSERT_NOT_NULL(frame);
  2932.  
  2933.     ODBoolean canEdit = kODFalse;
  2934.  
  2935.     if ( frame->GetLinkStatus(ev) == kODInLinkDestination )
  2936.     {
  2937.         if ( frame->EditInLink(ev) )
  2938.         {
  2939.             if ( frame->GetLinkStatus(ev) != kODInLinkDestination )
  2940.                 canEdit = kODTrue;
  2941.         }
  2942.         else
  2943.         {
  2944.             this->DoDialogBox(ev, frame, kErrorBoxID, kErrCantEditLinkDest);
  2945.         }
  2946.     }
  2947.     else
  2948.     {
  2949.         canEdit = kODTrue;
  2950.     }
  2951.  
  2952.     return canEdit;
  2953. }
  2954.  
  2955. //==============================================================================
  2956. #pragma mark    • Imaging •
  2957. //==============================================================================
  2958.  
  2959. //------------------------------------------------------------------------------
  2960. // Method:        Draw
  2961. // Origin:        ODPart
  2962. //
  2963. // Description:    This method is called when a facet of a part's display
  2964. //                frame intersects the invalidated portion of an OpenDoc
  2965. //                window. The invalidShape parameter passed in is the
  2966. //                portion of the facet which has been invalidated.
  2967. //
  2968. //                The part sets up the drawing environment using a
  2969. //                C++ helper class (CFocus) and then calls the
  2970. //                appropriate drawing method based on the frame's
  2971. //                viewType.
  2972. //------------------------------------------------------------------------------
  2973.  
  2974. void Cappuccino::Draw( Environment*        ev,
  2975.                        ODFacet*            facet,
  2976.                        ODShape*            invalidShape )
  2977. {
  2978.     SOM_Trace("Cappuccino","Draw");
  2979.  
  2980.     ASSERT_NOT_NULL(facet);
  2981.  
  2982.     // Focus the port and origin for drawing in our facet.
  2983.     // Note that this instance of the CFocusDrawingEnv class
  2984.     // is being allocated on the stack. When the execution
  2985.     // leaves the scope of this method, the destructor (which
  2986.     // cleans up the drawing environment) is automatically
  2987.     // called.
  2988.     CFocus initiateDrawing(ev, facet, invalidShape);
  2989.     
  2990.     ODTypeToken view = facet->GetFrame(ev)->GetViewType(ev);
  2991.     
  2992.     if ( view == gGlobals->fLargeIconView || view == gGlobals->fSmallIconView )
  2993.         this->DrawIconView(ev, facet);
  2994.     else if ( view == gGlobals->fThumbnailView )
  2995.         this->DrawThumbnailView(ev, facet);
  2996.     else
  2997.         this->DrawFrameView(ev, facet);
  2998. }
  2999.  
  3000. //------------------------------------------------------------------------------
  3001. // Method:        DrawFrameView
  3002. // Origin:        Cappuccino
  3003. //
  3004. // Description:    This method is called by the part when the frame being drawn is
  3005. //                in "frame" view.
  3006. //
  3007. //                Cappuccino really has not intrisic content. However, to provide
  3008. //                some visual display, we draw the class name at 80% of the
  3009. //                frame's current height using an bold font.
  3010. //------------------------------------------------------------------------------
  3011.  
  3012. void Cappuccino::DrawFrameView( Environment*    ev,
  3013.                                 ODFacet*        facet )
  3014. {
  3015.     SOM_Trace("Cappuccino","DrawFrameView");
  3016.  
  3017.     fContent->Draw(ev, facet, fSettings);
  3018. }
  3019.  
  3020. //------------------------------------------------------------------------------
  3021. // Method:        DrawIconView
  3022. // Origin:        Cappuccino
  3023. //
  3024. // Description:    This method is called by the part when the frame being
  3025. //                drawn is in "standard icon" view.
  3026. //
  3027. //                The part uses the Icon Utilities toolbox manager to
  3028. //                aid in drawing icons in active windows. The Guidelines
  3029. //                require a different appearance for selected icons in
  3030. //                inactive windows, which we do manually.
  3031. //------------------------------------------------------------------------------
  3032.  
  3033. void Cappuccino::DrawIconView( Environment*        ev,
  3034.                                ODFacet*            facet )
  3035. {
  3036.     SOM_Trace("Cappuccino","DrawIconView");
  3037.  
  3038.     ASSERT_NOT_NULL(facet);
  3039.  
  3040.     ODFrame*    frame        = facet->GetFrame(ev);
  3041.     ODTypeToken    viewType    = frame->GetViewType(ev);
  3042.     CFrameInfo*    frameInfo     = CFrameInfo::GetFrameInfo(ev, frame);
  3043.     
  3044.     IconTransformType transformType = ttNone;
  3045.     
  3046.     // Check to see if the facet is selected
  3047.     if ( facet->GetHighlight(ev) == kODFullHighlight )
  3048.         transformType = ttSelected;
  3049.     
  3050.     // Check to see if the frame has been opened into a part window.
  3051.     TempODWindow window = frameInfo->AcquirePartWindow(ev);
  3052.     if ( window && window->IsShown(ev) )
  3053.         transformType |= ttOpen;
  3054.     
  3055.     // Draw the icon.
  3056.     Rect iconRect;
  3057.     if ( viewType == gGlobals->fLargeIconView )
  3058.         SetRect(&iconRect, 0, 0, kODLargeIconSize, kODLargeIconSize);
  3059.     else // ( viewType == gGlobals->fSmallIconView )
  3060.         SetRect(&iconRect, 0, 0, kODSmallIconSize, kODSmallIconSize);
  3061.  
  3062.     CUsingLibraryResources res;
  3063.     PlotIconID(&iconRect, atAbsoluteCenter, transformType, kBaseResourceID);
  3064. }
  3065.  
  3066. //------------------------------------------------------------------------------
  3067. // Method:        DrawThumbnailView
  3068. // Origin:        Cappuccino
  3069. //
  3070. // Description:    This method is called by the part when the frame being
  3071. //                drawn is in "thumbnail" view.
  3072. //
  3073. //                The part uses a picture for its thumbnail view because
  3074. //                it has no intrinsic content. A picture resource is
  3075. //                probably not sufficient for parts with real content.
  3076. //------------------------------------------------------------------------------
  3077.  
  3078. void Cappuccino::DrawThumbnailView( Environment*    ev,
  3079.                                     ODFacet*        facet )
  3080. {
  3081.     SOM_Trace("Cappuccino","DrawThumbnailView");
  3082.  
  3083.     ASSERT_NOT_NULL(facet);
  3084.  
  3085.     // Create or retrieve a cached thumbnail picture.
  3086.     PicHandle thumbnail = this->GenerateThumbnail(ev, facet->GetFrame(ev));
  3087.     
  3088.     Rect bounds = (**thumbnail).picFrame;
  3089.     DrawPicture(thumbnail, &bounds);
  3090. }
  3091.  
  3092. //------------------------------------------------------------------------------
  3093. // Method:        GeometryChanged
  3094. // Origin:        ODPart
  3095. //
  3096. // Description:    This method is called when the ExternalTransform or
  3097. //                ClipShape of a facet on one this part's display frames
  3098. //                changes.
  3099. //------------------------------------------------------------------------------
  3100.  
  3101. void Cappuccino::GeometryChanged( Environment*    ev,
  3102.                                   ODFacet*        facet,
  3103.                                   ODBoolean        clipShapeChanged,
  3104.                                   ODBoolean        externalTransformChanged )
  3105. {
  3106.     SOM_Trace("Cappuccino","GeometryChanged");
  3107.  
  3108.     ASSERT_NOT_NULL(facet);
  3109.  
  3110.     if ( clipShapeChanged )
  3111.         // Specifying kODNULL means to invalidate the clipShape (which was
  3112.         // calculated from the usedShape).
  3113.         facet->Invalidate(ev, kODNULL, kODNULL);
  3114. }
  3115.  
  3116. //------------------------------------------------------------------------------
  3117. // Method:        HighlightChanged
  3118. // Origin:        ODPart
  3119. //
  3120. // Description:    This method is called when a facet....
  3121. //------------------------------------------------------------------------------
  3122.  
  3123. void Cappuccino::HighlightChanged(Environment* ev, ODFacet* facet)
  3124. {
  3125.     SOM_Trace("Cappuccino","HighlightChanged");
  3126.  
  3127.     ASSERT_NOT_NULL(facet);
  3128.  
  3129.     ODFrame* frame = facet->GetFrame(ev);
  3130.     
  3131.     // The frame view has no "special" drawing characteristics
  3132.     // when opened or selected, so we don't need to update our
  3133.     // content.
  3134.     if ( frame->GetViewType(ev) != gGlobals->fFrameView )
  3135.         frame->Invalidate(ev, kODNULL, kODNULL);
  3136. }
  3137.  
  3138. //------------------------------------------------------------------------------
  3139. // Method:        CanvasChanged
  3140. // Origin:        ODPart
  3141. //
  3142. // Description:    This method is called when a facet's canvas ...
  3143. //------------------------------------------------------------------------------
  3144.  
  3145. void Cappuccino::CanvasChanged( Environment*    ev,
  3146.                                 ODFacet*        facet)
  3147. {
  3148.     SOM_Trace("Cappuccino","CanvasChanged");
  3149.  
  3150. }
  3151.  
  3152. //------------------------------------------------------------------------------
  3153. // Method:        CanvasUpdated
  3154. // Origin:        ODPart
  3155. //
  3156. // Description:    This method is called when a canvas ...
  3157. //------------------------------------------------------------------------------
  3158.  
  3159. void Cappuccino::CanvasUpdated( Environment*    ev,
  3160.                                 ODCanvas*        canvas)
  3161. {
  3162.     SOM_Trace("Cappuccino","CanvasUpdated");
  3163.  
  3164. }
  3165.  
  3166. //------------------------------------------------------------------------------
  3167. // Method:        GetPrintResolution
  3168. // Origin:        ODPart
  3169. //
  3170. // Description:    This method is called when the minimum print resolution 
  3171. //                supported by this part is needed.
  3172. //------------------------------------------------------------------------------
  3173.  
  3174. ODULong Cappuccino::GetPrintResolution( Environment*    ev,
  3175.                                         ODFrame*        frame)
  3176. {
  3177.     SOM_Trace("Cappuccino","GetPrintResolution");
  3178.  
  3179.     return kMinImagingResolution;
  3180. }
  3181.  
  3182. //------------------------------------------------------------------------------
  3183. // Method:        FacetAdded
  3184. // Origin:        ODPart
  3185. //
  3186. // Description:    This method is called when any part adds a facet to
  3187. //                one of our display frames.
  3188. //
  3189. //                The part calls ViewTypeChanged to load the appropriate
  3190. //                resource for display in this facet and then activates
  3191. //                the frame if we are the root part of an active window.
  3192. //------------------------------------------------------------------------------
  3193.  
  3194. void Cappuccino::FacetAdded( Environment*    ev,
  3195.                              ODFacet*        facet )
  3196. {
  3197.     SOM_Trace("Cappuccino","FacetAdded");
  3198.  
  3199.     ASSERT_NOT_NULL(facet);
  3200.  
  3201.     ODFrame* frame = facet->GetFrame(ev);
  3202.     CFrameInfo* frameInfo = CFrameInfo::GetFrameInfo(ev, frame);
  3203.  
  3204.     // If a root facet is being added, the frame should be activated when the
  3205.     // window is "selected". This prevents OpenDoc from getting into an
  3206.     // ambiguous state of no part having the selection focus.
  3207.  
  3208.     if ( frame->IsRoot(ev) )
  3209.     {
  3210.         frameInfo->SetActiveFacet(facet);
  3211.         frameInfo->SetFrameReactivate(kODTrue);
  3212.     }
  3213.     
  3214.     // If a frame had all of its facets removed, the frame would have
  3215.     // hidden any of its part windows. If the frame becomes visible again,
  3216.     // by having a facet added to it, we will "show" the part window for
  3217.     // the frame.
  3218.     
  3219.     if ( CountFacets(ev, frame) == 1 )
  3220.     {
  3221.         TempODWindow window = frameInfo->AcquirePartWindow(ev);
  3222.         if ( window ) 
  3223.             window->Show(ev);
  3224.     }
  3225. }
  3226.  
  3227. //------------------------------------------------------------------------------
  3228. // Method:        FacetRemoved
  3229. // Origin:        ODPart
  3230. //
  3231. // Description:    This method is called when any part removes a facet
  3232. //                from one of our display frames.
  3233. //
  3234. //                The part just removes the "active" note from the
  3235. //                appropriate display frame if necessary since this
  3236. //                facet will not be available, nor active, again.
  3237. //------------------------------------------------------------------------------
  3238.  
  3239. void Cappuccino::FacetRemoved( Environment*    ev,
  3240.                                ODFacet*        facet )
  3241. {
  3242.     SOM_Trace("Cappuccino","FacetRemoved");
  3243.  
  3244.     ASSERT_NOT_NULL(facet);
  3245.  
  3246.     ODFrame*    frame           = facet->GetFrame(ev);
  3247.     TempODFrame    containingFrame = frame->AcquireContainingFrame(ev);
  3248.     CFrameInfo* frameInfo       = CFrameInfo::GetFrameInfo(ev, frame);
  3249.  
  3250.     // If the facet was the active facet, it can no longer be.
  3251.        if ( ODObjectsAreEqual(ev, frameInfo->GetActiveFacet(), facet) )
  3252.         frameInfo->SetActiveFacet(kODNULL);
  3253.  
  3254.     // If a frame has all of its facets removed and its containing frame set
  3255.     // to NULL, the frame becomes "hidden". If the frame owns a part window,
  3256.     // the part window should also be hidden.
  3257.     
  3258.     if ( CountFacets(ev, frame) == 0 && containingFrame == kODNULL )
  3259.     {
  3260.         TempODWindow window = frameInfo->AcquirePartWindow(ev);
  3261.         if ( window )
  3262.             window->Hide(ev);
  3263.     }
  3264. }
  3265.  
  3266. //------------------------------------------------------------------------------
  3267. // Method:        InvalidateFrameViews
  3268. // Origin:        Cappuccino
  3269. //
  3270. // Description:    This method is called when the content has changed in order
  3271. //                to cause all of the frames belonging to this part that are
  3272. //                in frame view to be redrawn with the new content.
  3273. //------------------------------------------------------------------------------
  3274.  
  3275. void Cappuccino::InvalidateFrameViews( Environment*        ev,
  3276.                                        ODShape*            invalidShape,
  3277.                                        ODCanvas*        biasCanvas )
  3278. {
  3279.     // Iterate over the frames we are displayed through and determine which
  3280.     // ones we need to invalidate.
  3281.     CListIterator fiter(fDisplayFrames);
  3282.     for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
  3283.             fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() )
  3284.     {
  3285.         // If the display frame is real (has been "connected" or was "added")
  3286.         // get its view type; otherwise, ignore it.
  3287.         if ( proxy->FrameIsLoaded(ev) )
  3288.         {
  3289.             ODFrame* frame = proxy->GetFrame(ev);
  3290.             
  3291.             if ( frame->GetViewType(ev) == gGlobals->fFrameView )
  3292.                 frame->Invalidate(ev, kODNULL, kODNULL);
  3293.         }
  3294.     }
  3295. }
  3296.  
  3297. //==============================================================================
  3298. #pragma mark    • Activation •
  3299. //==============================================================================
  3300.  
  3301. //------------------------------------------------------------------------------
  3302. // Method:        BeginRelinquishFocus
  3303. // Origin:        ODPart
  3304. //
  3305. // Description:    This method is called when another part (or possibly
  3306. //                ourself) is requesting a focus for one of its display
  3307. //                frames. Returning true means we are willing to give
  3308. //                up the requested focus.
  3309. //
  3310. //                The part willingly gives up any focus unless it is the
  3311. //                modal focus which we don't want to give up until we
  3312. //                are completely done displaying a modal dialog.
  3313. //------------------------------------------------------------------------------
  3314.  
  3315. ODBoolean Cappuccino::BeginRelinquishFocus( Environment*    ev,
  3316.                                             ODTypeToken        focus,
  3317.                                             ODFrame*        ownerFrame,
  3318.                                             ODFrame*        proposedFrame )
  3319. {
  3320.     SOM_Trace("Cappuccino","BeginRelinquishFocus");
  3321.  
  3322.     ODBoolean willRelinquish = kODTrue;
  3323.  
  3324.     // Another part is trying to put up a Modal dialog while we
  3325.     // are currently displaying ours. Deny the request.
  3326.     if ( focus == gGlobals->fModalFocus )
  3327.     {
  3328.         TempODPart proposedPart = ODAcquirePart(ev, proposedFrame);
  3329.         if ( ODObjectsAreEqual(ev, proposedPart, fSelf) == kODFalse )
  3330.             willRelinquish = kODFalse;
  3331.     }
  3332.     
  3333.     return willRelinquish;
  3334. }
  3335.  
  3336. //------------------------------------------------------------------------------
  3337. // Method:        CommitRelinquishFocus
  3338. // Origin:        ODPart
  3339. //
  3340. // Description:    This method is called when it is actually time to give
  3341. //                up a focus that had been requested by another part (or
  3342. //                possibly ourself).
  3343. //
  3344. //                The part calls its FocusLost method to handle the 
  3345. //                "reliquishing" of the particular focus.
  3346. //------------------------------------------------------------------------------
  3347.  
  3348. void Cappuccino::CommitRelinquishFocus( Environment*    ev,
  3349.                                         ODTypeToken        focus,
  3350.                                         ODFrame*        ownerFrame,
  3351.                                         ODFrame*        proposedFrame )
  3352. {
  3353.     SOM_Trace("Cappuccino","CommitRelinquishFocus");
  3354.  
  3355.     // We agreed to give up our FocusSet and now we are being asked to
  3356.     // do so.
  3357.     if ( focus == gGlobals->fSelectionFocus )
  3358.     {
  3359.         fSession->GetArbitrator(ev)->RelinquishFocusSet(ev, gGlobals->fUIFocusSet, ownerFrame);
  3360.         this->PartDeactivated(ev, ownerFrame);
  3361.     }
  3362. }
  3363.  
  3364. //------------------------------------------------------------------------------
  3365. // Method:        AbortRelinquishFocus
  3366. // Origin:        ODPart
  3367. //
  3368. // Description:    This method is called when another part (or possibly
  3369. //                ourself) requested a focus for one of its display
  3370. //                frames, but we returned kODFalse from
  3371. //                BeginRelinqishFocus for one, or all, of the requested
  3372. //                focus. At this point, we are being told to resume
  3373. //                ownership of the focus.
  3374. //------------------------------------------------------------------------------
  3375.  
  3376. void Cappuccino::AbortRelinquishFocus( Environment*        ev,
  3377.                                        ODTypeToken        focus,
  3378.                                        ODFrame*            ownerFrame,
  3379.                                        ODFrame*            proposedFrame )
  3380. {
  3381.     SOM_Trace("Cappuccino","AbortRelinquishFocus");
  3382.  
  3383.     // Some parts may have suspended some events in the BeginRelinquishFocus
  3384.     // method. If so, they would resume those events here.
  3385. }
  3386.  
  3387. //------------------------------------------------------------------------------
  3388. // Method:        FocusAcquired
  3389. // Origin:        ODPart
  3390. //
  3391. // Description:    This method is called when the Arbitrator has
  3392. //                registered us as the "owner" of the particular focus.
  3393. //                This can occur if we are explicitly assigned a focus, or if a
  3394. //                focus is transfered to one of the part's display frames.
  3395. //
  3396. //                The part will request its complete focus set to become "active".
  3397. //                If the part is successful, we notify ourself to become active.
  3398. //------------------------------------------------------------------------------
  3399.  
  3400. void Cappuccino::FocusAcquired( Environment*    ev,
  3401.                                 ODTypeToken        focus,
  3402.                                 ODFrame*        ownerFrame )
  3403. {
  3404.     SOM_Trace("Cappuccino","FocusAcquired");
  3405.  
  3406.     ODArbitrator* arbitrator =  fSession->GetArbitrator(ev);
  3407.  
  3408.     if ( gGlobals->fUIFocusSet->Contains(ev, focus) )
  3409.     {
  3410.         if ( arbitrator->RequestFocusSet(ev, gGlobals->fUIFocusSet, ownerFrame) )
  3411.             this->PartActivated(ev, ownerFrame);
  3412.     }
  3413. }
  3414.  
  3415. //------------------------------------------------------------------------------
  3416. // Method:        FocusLost
  3417. // Origin:        ODPart
  3418. //
  3419. // Description:    This method is called when the Arbitrator has
  3420. //                unregistered us as the "owner" of the particular
  3421. //                focus.
  3422. //
  3423. //                The part unmarks the active frame if the selection
  3424. //                focus is lost.
  3425. //------------------------------------------------------------------------------
  3426.  
  3427. void Cappuccino::FocusLost( Environment*    ev,
  3428.                             ODTypeToken        focus,
  3429.                             ODFrame*        ownerFrame )
  3430. {
  3431.     SOM_Trace("Cappuccino","FocusLost");
  3432.  
  3433.     if ( gGlobals->fUIFocusSet->Contains(ev, focus) )
  3434.     {
  3435.         fSession->GetArbitrator(ev)
  3436.                 ->RelinquishFocusSet(ev, gGlobals->fUIFocusSet, ownerFrame);
  3437.         
  3438.         this->PartDeactivated(ev, ownerFrame);
  3439.     }
  3440. }
  3441.  
  3442. //------------------------------------------------------------------------------
  3443. // Method:        RelinquishAllFoci
  3444. // Origin:        Cappuccino
  3445. //
  3446. // Description:    This method is called when a frame is going away. The method
  3447. //                relinquishes all foci the frame owns.
  3448. //------------------------------------------------------------------------------
  3449.  
  3450. void Cappuccino::RelinquishAllFoci( Environment*    ev,
  3451.                                     ODFrame*        frame )
  3452. {
  3453.     SOM_Trace("Cappuccino","RelinquishAllFoci");
  3454.  
  3455.     if ( HasAnyFocusInSet(ev, frame, gGlobals->fUIFocusSet) )
  3456.     {
  3457.         fSession->GetArbitrator(ev)->RelinquishFocusSet(ev, gGlobals->fUIFocusSet, frame);
  3458.         this->PartDeactivated(ev, frame);
  3459.     }
  3460.     
  3461.     // We also need to relinquish any other foci that we might have in this
  3462.     // routine.  In order to do this, call the Arbitrator's AcquireFocusOwner
  3463.     // function, and if it is this frame, call RelinquishFocus for that focus
  3464.     // type and do whatever we need to do when we are giving up that focus.
  3465. }
  3466.  
  3467. //------------------------------------------------------------------------------
  3468. // Method:        PartActivated
  3469. // Origin:        Cappuccino
  3470. //
  3471. // Description:    This method is called when the part has successfully acquired
  3472. //                the set of foci which allow it to "run".
  3473. //------------------------------------------------------------------------------
  3474.  
  3475. void Cappuccino::PartActivated( Environment*    ev,
  3476.                                 ODFrame*        frame )
  3477. {
  3478.     SOM_Trace("Cappuccino","PartActivated");
  3479.     
  3480.     // We are required to re-validate the menubar before displaying it because
  3481.     // any part can/could swap the base menubar at any time.
  3482.     if ( !gGlobals->fMenuBar->IsValid(ev) )
  3483.         this->BuildMenuBar(ev);
  3484.             
  3485.     // Display our menu bar.
  3486.     gGlobals->fMenuBar->Display(ev);
  3487.     
  3488.     // And set our "active" state.
  3489.     CFrameInfo* frameInfo = CFrameInfo::GetFrameInfo(ev, frame);
  3490.     frameInfo->SetFrameActive(kODTrue);
  3491. }
  3492.  
  3493. //------------------------------------------------------------------------------
  3494. // Method:        PartDeactivated
  3495. // Origin:        Cappuccino
  3496. //
  3497. // Description:    This method is called when the part has been asked to
  3498. //                relinquish the foci from its UI focus set.
  3499. //------------------------------------------------------------------------------
  3500.  
  3501. void Cappuccino::PartDeactivated( Environment*        ev,
  3502.                                   ODFrame*            frame )
  3503. {
  3504.     SOM_Trace("Cappuccino","PartDeactivated");
  3505.     
  3506.     // And set our "active" state.
  3507.     CFrameInfo* frameInfo = CFrameInfo::GetFrameInfo(ev, frame);
  3508.     frameInfo->SetFrameActive(kODFalse);
  3509. }
  3510.  
  3511. //------------------------------------------------------------------------------
  3512. // Method:        ActivateFrame
  3513. // Origin:        Cappuccino
  3514. //
  3515. // Description:    This method is called by the part when a kODEvtMouseUp
  3516. //                occurs in an inactive frame in an active window, and
  3517. //                when an OpenDoc document comes forward.
  3518. //
  3519. //                The part activates the frame by requesting the
  3520. //                UIFocusSet (created in Initialize) and by calling
  3521. //                FocusAcquired if we were successful. The method
  3522. //                returns true if no problems were encountered as a
  3523. //                signal to the caller that the frame is now "active".
  3524. //------------------------------------------------------------------------------
  3525.  
  3526. ODBoolean Cappuccino::ActivateFrame( Environment*    ev,
  3527.                                      ODFrame*        frame )
  3528. {
  3529.     SOM_Trace("Cappuccino","ActivateFrame");
  3530.  
  3531.     ODBoolean activated = kODFalse;
  3532.  
  3533.     // Request the set of foci necessary to become active.
  3534.     if ( fSession->GetArbitrator(ev)
  3535.             ->RequestFocusSet(ev, gGlobals->fUIFocusSet, frame) )
  3536.     {
  3537.         // Activate the part.
  3538.         this->PartActivated(ev, frame);
  3539.         // We were able to become active.
  3540.         activated = kODTrue;
  3541.     }
  3542.     
  3543.     // Let our caller know we succeded or failed.
  3544.     return activated;
  3545. }
  3546.  
  3547. //------------------------------------------------------------------------------
  3548. // Method:        WindowActivating
  3549. // Origin:        Cappuccino
  3550. //
  3551. // Description:    This method is called by the part when a window activation
  3552. //                event (kODEvtActivate) occurs.
  3553. //
  3554. //                The part remembers the frame's active state and restores it when
  3555. //                events come in. If the frame is active and the window is being
  3556. //                sent into the background, remember to reactivate the part when
  3557. //                the window is reactivated.
  3558. //------------------------------------------------------------------------------
  3559.  
  3560. void Cappuccino::WindowActivating( Environment*        ev,
  3561.                                    ODFrame*            frame,
  3562.                                    ODBoolean        activating )
  3563. {
  3564.     SOM_Trace("Cappuccino","WindowActivating");
  3565.  
  3566.     ASSERT_NOT_NULL(frame);
  3567.  
  3568.     CFrameInfo* frameInfo = CFrameInfo::GetFrameInfo(ev, frame);
  3569.     
  3570.     // The window is being activated and we had the selection focus when
  3571.     // the window was deactivated, so activate ourself.
  3572.     if ( activating && frameInfo->FrameNeedsReactivating() )
  3573.     {
  3574.         this->ActivateFrame(ev, frame);
  3575.         frameInfo->SetFrameReactivate(kODFalse);
  3576.     }
  3577.     // The window is being deactivated and we are the active part.
  3578.     // Give up our foci and remind ourselves that we need to request
  3579.     // the focus when the window is reactivated.
  3580.     else if ( !activating && frameInfo->IsFrameActive() )
  3581.     {
  3582.         frameInfo->SetFrameReactivate(kODTrue);
  3583.     }
  3584. }
  3585.  
  3586. //==============================================================================
  3587. #pragma mark    • Event Handling •
  3588. //==============================================================================
  3589.  
  3590. //------------------------------------------------------------------------------
  3591. // Method:        HandleEvent
  3592. // Origin:        ODPart
  3593. //
  3594. // Description:    The method is called when an event, which falls into
  3595. //                the category of an owned focus, occurs. The two
  3596. //                exceptions to this are "mouse movement" events and 
  3597. //                embedded frame events, which can occur when a part
  3598. //                owns no foci.
  3599. //
  3600. //                The part returns true if the event was handled.
  3601. //------------------------------------------------------------------------------
  3602.  
  3603.  
  3604. ODBoolean Cappuccino::HandleEvent( Environment*        ev,
  3605.                                    ODEventData*        event,
  3606.                                    ODFrame*            frame,
  3607.                                    ODFacet*            facet,
  3608.                                    ODEventInfo*        eventInfo )
  3609. {
  3610.     SOM_Trace("Cappuccino","HandleEvent");
  3611.  
  3612.     ODBoolean    eventHandled = kODFalse;
  3613.  
  3614.     // Event handling is basically the same as standard Macintosh applications,
  3615.     // except that the events have been renamed for cross-platform compatability.
  3616.     
  3617.     switch ( event->what )
  3618.     {
  3619.         case kODEvtMouseDown:
  3620.         case kODEvtMouseUp:
  3621.             eventHandled = this->HandleMouseEvent(ev, event, facet, eventInfo);
  3622.             break;
  3623.             
  3624.         case kODEvtMenu:
  3625.             eventHandled = this->HandleMenuEvent(ev, event, frame);
  3626.             break;
  3627.  
  3628.         case kODEvtActivate:
  3629.             // We are being notified that a window we are displayed in has
  3630.             // just been de/activated (un/hilighted).
  3631.             this->WindowActivating(ev, frame, (event->modifiers & activeFlag));
  3632.             eventHandled = kODTrue;
  3633.             break;
  3634.     
  3635.         case kODEvtMouseEnter:
  3636.         case kODEvtMouseLeave:
  3637.             SetCursor(&ODQDGlobals.arrow);
  3638.             eventHandled = kODTrue;
  3639.             break;
  3640.  
  3641.         case kODEvtMouseWithin:
  3642.             eventHandled = kODTrue;
  3643.             break;
  3644.  
  3645.         // Other events a part might handle
  3646.         case kODEvtNull:
  3647.         case kODEvtMouseDownEmbedded:
  3648.         case kODEvtMouseUpEmbedded:
  3649.         case kODEvtMouseDownBorder:
  3650.         case kODEvtMouseUpBorder:
  3651.         case kODEvtWindow:
  3652.         case kODEvtKeyDown:
  3653.         case kODEvtKeyUp:
  3654.         case kODEvtAutoKey:
  3655.         case kODEvtOS:
  3656.         case kODEvtDisk:
  3657.         
  3658.         default:
  3659.             break;
  3660.     }
  3661.  
  3662.     return eventHandled;
  3663. }
  3664.  
  3665. //------------------------------------------------------------------------------
  3666. // Method:        BuildMenuBar
  3667. // Origin:        Cappuccino
  3668. //
  3669. // Description:    This method is called when the menubar needs to be created or
  3670. //                changed (because it has become invalid).
  3671. //------------------------------------------------------------------------------
  3672.  
  3673. void Cappuccino::BuildMenuBar( Environment* ev )
  3674. {
  3675.     if (gGlobals->fMenuBar == kODNULL || !gGlobals->fMenuBar->IsValid(ev))
  3676.     {
  3677.         ODBoolean changingBaseMenuBar = (gGlobals->fMenuBar != kODNULL);
  3678.         
  3679.         if (changingBaseMenuBar)
  3680.         {
  3681.             // Remove our menus from the old menubar.
  3682.             for (ODSShort index = 0; index < kNumMenus; index++)
  3683.             {
  3684.                 ODSShort id = kBaseMenuID + index;
  3685.                 gGlobals->fMenuBar->RemoveMenu(ev, id);
  3686.             }
  3687.         }
  3688.         
  3689.         ODReleaseObject(ev, gGlobals->fMenuBar);
  3690.  
  3691.         // It is required that parts instantiate their menu bars from 
  3692.         // the base OpenDoc menu bar. This maintains consistency in the
  3693.         // default menu items and their placement.
  3694.         // Since the object is a copy, we can add and subtract menus and
  3695.         // items without affecting other running parts.
  3696.         gGlobals->fMenuBar = fSession->GetWindowState(ev)->CopyBaseMenuBar(ev);
  3697.         
  3698.         // Add our resource-based menus and register all the editor specific
  3699.         // command numbers.
  3700.         CUsingLibraryResources res;
  3701.         for (ODSShort index = 0; index < kNumMenus; index++)
  3702.         {
  3703.             ODSShort id = kBaseMenuID + index;
  3704.             
  3705.             MenuHandle menu = GetMenu(id);
  3706.             if (menu != kODNULL)
  3707.                 gGlobals->fMenuBar->AddMenuLast(ev, id, menu, fSelf);
  3708.         }
  3709.         
  3710.         // Register commands for our menu items.
  3711.         gGlobals->fMenuBar->RegisterCommand(ev, kCommandSpeak,    kMiscMenuID, 1);
  3712. #ifndef qViewerBuild
  3713.         gGlobals->fMenuBar->RegisterCommand(ev, kCommandSetText,  kMiscMenuID, 3);
  3714.         gGlobals->fMenuBar->RegisterCommand(ev, kCommandSettings, kMiscMenuID, 4);
  3715. #endif
  3716.     }
  3717. }
  3718.  
  3719. //------------------------------------------------------------------------------
  3720. // Method:        AdjustMenus
  3721. // Origin:        ODPart
  3722. //
  3723. // Description:    This method is called when a kODEvtMouseDown event occurs in the
  3724. //                menubar and the part owns the "menu" focus, or when the part is
  3725. //                root part of a document.
  3726. //
  3727. //                The part first verifies that the base menubar has not been
  3728. //                modified, then enables the menu items and changes their names
  3729. //                where appropriate (eg. About Cappuccino...).
  3730. //------------------------------------------------------------------------------
  3731.  
  3732. void Cappuccino::AdjustMenus( Environment*    ev,
  3733.                               ODFrame*        frame )
  3734. {
  3735.     SOM_Trace("Cappuccino","AdjustMenus");
  3736.  
  3737.     // The menubar object always calls the root part's AdjustMenus method before
  3738.     // calling the menu focus owner's. Because of this, we need to validate the
  3739.     // menubar in the case where we are the root part.
  3740.     if ( frame->IsRoot(ev) )
  3741.     {
  3742.         // We are required to re-validate the menubar before displaying it because
  3743.         // any part can/could swap the base menubar at any time.
  3744.         if ( !gGlobals->fMenuBar->IsValid(ev) )
  3745.             this->BuildMenuBar(ev);
  3746.         
  3747.          // PRINTING: Always enable Page Setup and Print when the root part.
  3748.          // Note: We call AcquireCurrentMenuBar here because, if we support
  3749.          // embedding, we have to enable the print menus whenever we are the
  3750.          // root part of the window, whether or not we have the menu focus.
  3751.         TempODMenuBar mbar = fSession->GetWindowState(ev)->AcquireCurrentMenuBar(ev);
  3752.         mbar->EnableCommand(ev, kODCommandPageSetup, kODTrue);
  3753.         mbar->EnableCommand(ev, kODCommandPrint, kODTrue);
  3754.     }
  3755.  
  3756.     // -- Cappuccino menu items --
  3757.     
  3758. #ifndef qViewerBuild
  3759.     gGlobals->fMenuBar->EnableCommand(ev, kCommandSettings, !fReadOnlyStorage);
  3760.     gGlobals->fMenuBar->EnableCommand(ev, kCommandSetText,  !fReadOnlyStorage);
  3761. #endif
  3762.  
  3763.     gGlobals->fMenuBar->EnableCommand(ev, kCommandSpeak, HasSpeech() && 
  3764.                                                 !fContent->IsEmpty());
  3765.  
  3766.     // -- Standard menu items --
  3767.  
  3768.     // Enable the "View As Window" command always when we're not at the root.
  3769.     gGlobals->fMenuBar->EnableCommand(ev, kODCommandViewAsWin, !frame->IsRoot(ev));
  3770.     
  3771.     // Enable/disable the clipboard-related menu items
  3772.     this->AdjustClipboardComands(ev, frame);
  3773.  
  3774.     TRY
  3775.         ODArbitrator* arbitrator = fSession->GetArbitrator(ev);
  3776.         TempODFrame menuOwner = arbitrator->AcquireFocusOwner(ev, gGlobals->fMenuFocus);
  3777.         
  3778.         // There is no need to load a resource, create an ODIText object, set the menubar,
  3779.         // and cleanup, if we don't own the menu focus.
  3780.         if ( ODObjectsAreEqual(ev, frame, menuOwner) )
  3781.         {
  3782.             Str63 text;
  3783.             
  3784.             // Get the "about" string from our library's resources.
  3785.             // (note: ODGetIndString focuses the resource fork for us)
  3786.             ODGetIndString(text, kMenuStringResID, kAboutTextID);
  3787.             // Create an IText object to pass into the menubar.
  3788.             TempODIText    menuItem = CreateIText(gGlobals->fEditorsScript, 
  3789.                                                gGlobals->fEditorsLanguage,
  3790.                                                (StringPtr) &text);
  3791.             // Change the "About" menu item text for our part.
  3792.             gGlobals->fMenuBar->SetItemString(ev, kODCommandAbout, menuItem);
  3793.         }
  3794.     CATCH_ALL
  3795.         // consume exception
  3796.     ENDTRY
  3797. }
  3798.  
  3799. //------------------------------------------------------------------------------
  3800. // Method:        HandleMenuEvent
  3801. // Origin:        Cappuccino
  3802. //
  3803. // Description:    This method is called by the part when a menu event is
  3804. //                received.
  3805. //
  3806. //                Using the menu bar object, we determine what the menu
  3807. //                command is, and call the appropriate method to handle
  3808. //                it.
  3809. //------------------------------------------------------------------------------
  3810.  
  3811. ODBoolean Cappuccino::HandleMenuEvent( Environment*        ev,
  3812.                                        ODEventData*        event,
  3813.                                        ODFrame*            frame )
  3814. {
  3815.     SOM_Trace("Cappuccino","HandleMenuEvent");
  3816.  
  3817.     ODULong        menuResult    = event->message;
  3818.     ODUShort    menu        = HiWord(menuResult);
  3819.     ODUShort    item        = LoWord(menuResult);
  3820.  
  3821.     switch ( gGlobals->fMenuBar->GetCommand(ev, menu, item) )
  3822.     {
  3823.         // -- Cappuccino menu items --
  3824.         
  3825. #ifdef powerc
  3826.         case kCommandSpeak:
  3827.             if ( HasSpeech() )
  3828.             {
  3829.                 if ( SpeakString(fContent->GetString()) != noErr )
  3830.                 {
  3831.                     this->DoDialogBox(ev, frame, kErrorBoxID, 
  3832.                                       kErrSpeechManagerProblem);
  3833.                 }
  3834.             }
  3835.             break;
  3836. #endif
  3837.         
  3838. #ifndef qViewerBuild
  3839.         case kCommandSettings:
  3840.             this->ShowSettingsDialog(ev, frame);
  3841.             break;
  3842.             
  3843.         case kCommandSetText:
  3844.             this->ShowSetTextDialog(ev, frame);
  3845.             break;
  3846. #endif
  3847.         
  3848.         // -- Standard menu items --
  3849.  
  3850.         case kODCommandAbout:    
  3851.             this->DoDialogBox(ev, frame, kAboutBoxID);
  3852.             break;
  3853.  
  3854.         case kODCommandPageSetup:
  3855.             // If the user modified page setup, the print
  3856.             // job needs to be saved. We don't call our
  3857.             // internal SetDirty() method because the change
  3858.             // doesn't affect content.
  3859.             if ( fPrinter && fPrinter->PageSetup(ev) )
  3860.                 ODGetDraft(ev, fSelf)->SetChangedFromPrev(ev);
  3861.             break;
  3862.             
  3863.         case kODCommandPrint:
  3864.             if ( fPrinter )
  3865.                 fPrinter->PrintDocument(ev, frame);
  3866.             break;
  3867.  
  3868.         case kODCommandCut:
  3869.             this->DoCut(ev, frame);
  3870.             break;
  3871.             
  3872.         case kODCommandCopy:
  3873.             this->DoCopy(ev, frame);
  3874.             break;
  3875.             
  3876.         case kODCommandPaste:
  3877.             this->DoPaste(ev, frame);
  3878.             break;
  3879.         
  3880.         case kODCommandPasteAs:
  3881.             this->DoPasteAs(ev, frame);
  3882.             break;
  3883.  
  3884.         case kODCommandClear:
  3885.             this->DoClear(ev, frame);
  3886.             break;
  3887.  
  3888.         case kODCommandViewAsWin:
  3889.             this->Open(ev, frame);
  3890.             break;
  3891.  
  3892.         // Other commands a part might handle
  3893.         case kODCommandOpen:
  3894.         case kODCommandInsert:
  3895.         case kODCommandSelectAll:
  3896.         case kODCommandGetPartInfo:
  3897.         case kODCommandPreferences:
  3898.  
  3899.         default:
  3900.             return kODFalse;
  3901.     }
  3902.         
  3903.     return kODTrue;
  3904. }
  3905.  
  3906. //------------------------------------------------------------------------------
  3907. // Method:        HandleMouseEvent
  3908. // Origin:        Cappuccino
  3909. //
  3910. // Description:    This method is called by the part when a mouse event
  3911. //                is recieved.
  3912. //
  3913. //                A typical part would determine the event type(up/down)
  3914. //                and respond appropriately, but we have no "real"
  3915. //                content model, so we activate the part as appropriate
  3916. //                and call a generic method to handle the event.
  3917. //
  3918. // Remember:    When a frame is inactive, the first mouse up event
  3919. //                should activate it; inactive frames do not recieve
  3920. //                kODEvtMouseDown events.
  3921. //------------------------------------------------------------------------------
  3922.  
  3923. ODBoolean Cappuccino::HandleMouseEvent( Environment*    ev,
  3924.                                         ODEventData*    event,
  3925.                                         ODFacet*        facet,
  3926.                                         ODEventInfo*    eventInfo )
  3927. {
  3928.     SOM_Trace("Cappuccino","HandleMouseEvent");
  3929.  
  3930.     // If the facet parameter is invalid, the mouse up occurred outside the
  3931.     // bounds of a Modal window, otherwise it should be treated normally.
  3932.     
  3933.     if ( facet != kODNULL )
  3934.     {
  3935.         if ( event->what == kODEvtMouseUp )
  3936.         {
  3937.             ODWindow* window = facet->GetWindow(ev);
  3938.  
  3939.             TRY
  3940.                 // Activate inactive windows on the first mouse up event.
  3941.                 if ( !window->IsActive(ev) )
  3942.                     window->Select(ev);
  3943.                 // Activate the frame (if needed) on all subsequent mouse up events.
  3944.                 else
  3945.                 {
  3946.                     ODFrame* frame = facet->GetFrame(ev);
  3947.                     
  3948.                     // Get our state information from the PartInfo of the frame.
  3949.                     CFrameInfo* frameInfo = CFrameInfo::GetFrameInfo(ev, frame);
  3950.                                     
  3951.                     // If this frame is not the active one, activate it by requesting
  3952.                     // the appropriate foci.
  3953.                     
  3954.                     if ( !frameInfo->IsFrameActive() )
  3955.                     {
  3956.                         if ( this->ActivateFrame(ev, frame) )
  3957.                             // Keep track of which facet was the last active for positioning
  3958.                             // child windows.
  3959.                             frameInfo->SetActiveFacet(facet);
  3960.                         else
  3961.                             // We were unable to acquire the necessary focus and activate it.
  3962.                             return kODFalse;
  3963.                     }
  3964.                 }
  3965.             CATCH_ALL
  3966.             ENDTRY
  3967.         }
  3968.         else if ( event->what == kODEvtMouseDown )                
  3969.         {
  3970.             this->DoMouseDown(ev, event, facet, eventInfo);
  3971.         }
  3972.     }
  3973.     else
  3974.     {
  3975.         // User clicked outside the bounds of a Modal window, though we actually
  3976.         // never display one.
  3977.         
  3978.         SysBeep(1);
  3979.     }
  3980.  
  3981.     return kODTrue;
  3982. }
  3983.  
  3984. //------------------------------------------------------------------------------
  3985. // Method:        DoMouseDown
  3986. // Origin:        Cappuccino
  3987. //
  3988. // Description:    This method is called by the part to handle mouse
  3989. //                events.
  3990. //------------------------------------------------------------------------------
  3991.  
  3992. void Cappuccino::DoMouseDown( Environment*        ev,
  3993.                               ODEventData*        event,
  3994.                               ODFacet*            facet,
  3995.                               ODEventInfo*        eventInfo )
  3996. {
  3997.     SOM_Trace("Cappuccino","DoMouseEvent");
  3998.     
  3999.     // If you part allows selections or a lasso tool, this is where you
  4000.     // would handle those events. This is also where you would handle
  4001.     // program controlled buttons or controls.
  4002.     
  4003.     // If the mouse was clicked on something that is draggable, then we
  4004.     // need to call WaitMouseMoved and possibly InitiateDrag.
  4005.     if ( WaitMouseMoved(event->where) )
  4006.     {
  4007.         (void) this->InitiateDrag(ev, event, facet, eventInfo->where);
  4008.     }
  4009.     else
  4010.     {
  4011.         Point where;
  4012.  
  4013.         // Get the localized mouse coordinates from the Event Info.
  4014.         where.h = FixedToInt(eventInfo->where.x);
  4015.         where.v = FixedToInt(eventInfo->where.y);
  4016.     
  4017.         // Handle the mouse down event.
  4018.     }
  4019. }
  4020.  
  4021. //------------------------------------------------------------------------------
  4022. // Method:        DoDialogBox
  4023. // Origin:        Cappuccino
  4024. //
  4025. // Description:    This method is called by the part when a dialog needs to be
  4026. //                displayed (eg. the About Box). If a valid error number is passed
  4027. //                in, an error dialog will be displayed.
  4028. //------------------------------------------------------------------------------
  4029.  
  4030. void Cappuccino::DoDialogBox( Environment*    ev,
  4031.                               ODFrame*        frame,
  4032.                               ODSShort        dialogID,
  4033.                               ODUShort        errorNumber )
  4034. {
  4035.     SOM_Trace("Cappuccino","DoDialogBox");
  4036.  
  4037.     ODFrame* focusFrame = frame;
  4038.     
  4039.     // If the calling method does not have a frame available to it, we need to
  4040.     // locate a frame to use for requesting the modal focus. Find the first valid
  4041.     // frame in our display frames list.
  4042.     if ( focusFrame == kODNULL )
  4043.     {
  4044.         CListIterator fiter(fDisplayFrames);
  4045.         for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
  4046.                 fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() )
  4047.         {
  4048.             if ( proxy->FrameIsLoaded(ev) )
  4049.                 focusFrame = proxy->GetFrame(ev);
  4050.             if ( focusFrame ) break;
  4051.         }
  4052.     }
  4053.     
  4054.     // Our dialog boxes are modal so we must request the Modal focus to prevent
  4055.     // multiple modal dialogs being displayed simultaneously.
  4056.     
  4057.     TempFocus modalFocus(ev, gGlobals->fModalFocus, focusFrame);
  4058.     if ( modalFocus.Request() )
  4059.     {
  4060.         ODSShort itemHit;
  4061.  
  4062.         // Dim the frontmost document window.
  4063.         fSession->GetWindowState(ev)->DeactivateFrontWindows(ev);
  4064.                 
  4065.         CUsingLibraryResources res;
  4066.  
  4067.         DialogPtr dialog = GetNewDialog(dialogID, kODNULL, (WindowPtr) -1L);
  4068.         if ( dialog )
  4069.         {
  4070.             if ( errorNumber > 0 )
  4071.             {
  4072.                 Handle    itemHandle;
  4073.                 Rect    itemRect;
  4074.                 short    itemType;
  4075.                 Str255    errStr;
  4076.                 
  4077.                 GetIndString(errStr, kErrorStringResID, errorNumber);
  4078.                 GetDialogItem(dialog, kErrStrFieldItem, &itemType, &itemHandle, &itemRect);
  4079.                 SetDialogItemText(itemHandle, errStr);
  4080.                 
  4081.                 // We don't need the cancel button for an error dialog.
  4082.                 HideDialogItem(dialog, cancel);
  4083.  
  4084.                 SetDialogDefaultItem(dialog, ok);
  4085.             }
  4086.             
  4087.             SetCursor(&ODQDGlobals.arrow);
  4088.             ShowWindow(dialog);
  4089.             ModalDialog(kODNULL, &itemHit);
  4090.             DisposeDialog(dialog);
  4091.         }
  4092.         else
  4093.         {
  4094.             // Could not load About box dialog... something is amiss.
  4095.             SysBeep(2);
  4096.         }
  4097.         
  4098.         // Hilite the frontmost document window.
  4099.         fSession->GetWindowState(ev)->ActivateFrontWindows(ev);
  4100.     }
  4101.     else
  4102.     {
  4103.         // If we can't get the modal focus, then another modal dialog is
  4104.         // already being displayed.
  4105.         SysBeep(2);
  4106.     }
  4107. }
  4108.  
  4109. //------------------------------------------------------------------------------
  4110. // Method:        ShowSetTextDialog
  4111. // Origin:        Cappuccino
  4112. //
  4113. // Description:    The method is called by the part when the user chooses the
  4114. //                Set Text menu item.
  4115. //------------------------------------------------------------------------------
  4116.  
  4117. void Cappuccino::ShowSettingsDialog( Environment*    ev,
  4118.                                      ODFrame*        frame )
  4119. {
  4120.     SOM_Trace("Cappuccino","ShowSettingsDialog");
  4121.     
  4122.     CSettings::DoSettingsDialog(ev, frame, this, fSettings);
  4123. }
  4124.  
  4125. //------------------------------------------------------------------------------
  4126. // Method:        ShowSetTextDialog
  4127. // Origin:        Cappuccino
  4128. //
  4129. // Description:    The method is called by the part when the user chooses the
  4130. //                Set Text menu item.
  4131. //------------------------------------------------------------------------------
  4132.  
  4133. void Cappuccino::ShowSetTextDialog( Environment*    ev,
  4134.                                     ODFrame*        frame )
  4135. {
  4136.     SOM_Trace("Cappuccino","ShowSetTextDialog");
  4137.     
  4138.     CCappuccinoContent::DoSetTextDialog(ev, frame, this, fContent);
  4139. }
  4140.  
  4141.